]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOUserClient.cpp
29fb9577f811769ebc5bbce05d1b0b47f921bfae
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
1 /*
2 * Copyright (c) 1998-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
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 <libkern/OSDebug.h>
43 #include <sys/proc.h>
44 #include <sys/kauth.h>
45
46 #if CONFIG_MACF
47
48 extern "C" {
49 #include <security/mac_framework.h>
50 };
51 #include <sys/kauth.h>
52
53 #define IOMACF_LOG 0
54
55 #endif /* CONFIG_MACF */
56
57 #include <IOKit/assert.h>
58
59 #include "IOServicePrivate.h"
60 #include "IOKitKernelInternal.h"
61
62 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
63 #define SCALAR32(x) ((uint32_t )x)
64 #define ARG32(x) ((void *)SCALAR32(x))
65 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
66 #define REF32(x) ((int)(x))
67
68 enum
69 {
70 kIOUCAsync0Flags = 3ULL,
71 kIOUCAsync64Flag = 1ULL
72 };
73
74 #if IOKITSTATS
75
76 #define IOStatisticsRegisterCounter() \
77 do { \
78 reserved->counter = IOStatistics::registerUserClient(this); \
79 } while (0)
80
81 #define IOStatisticsUnregisterCounter() \
82 do { \
83 if (reserved) \
84 IOStatistics::unregisterUserClient(reserved->counter); \
85 } while (0)
86
87 #define IOStatisticsClientCall() \
88 do { \
89 IOStatistics::countUserClientCall(client); \
90 } while (0)
91
92 #else
93
94 #define IOStatisticsRegisterCounter()
95 #define IOStatisticsUnregisterCounter()
96 #define IOStatisticsClientCall()
97
98 #endif /* IOKITSTATS */
99
100 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
101
102 // definitions we should get from osfmk
103
104 //typedef struct ipc_port * ipc_port_t;
105 typedef natural_t ipc_kobject_type_t;
106
107 #define IKOT_IOKIT_SPARE 27
108 #define IKOT_IOKIT_CONNECT 29
109 #define IKOT_IOKIT_OBJECT 30
110
111 extern "C" {
112
113 extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
114 ipc_kobject_type_t type );
115
116 extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
117
118 extern mach_port_name_t iokit_make_send_right( task_t task,
119 io_object_t obj, ipc_kobject_type_t type );
120
121 extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta );
122
123 extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
124
125 extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
126
127 extern ipc_port_t master_device_port;
128
129 extern void iokit_retain_port( ipc_port_t port );
130 extern void iokit_release_port( ipc_port_t port );
131 extern void iokit_release_port_send( ipc_port_t port );
132
133 extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type );
134
135 #include <mach/mach_traps.h>
136 #include <vm/vm_map.h>
137
138 } /* extern "C" */
139
140
141 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
142
143 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
144
145 class IOMachPort : public OSObject
146 {
147 OSDeclareDefaultStructors(IOMachPort)
148 public:
149 OSObject * object;
150 ipc_port_t port;
151 UInt32 mscount;
152 UInt8 holdDestroy;
153
154 static IOMachPort * portForObject( OSObject * obj,
155 ipc_kobject_type_t type );
156 static bool noMoreSendersForObject( OSObject * obj,
157 ipc_kobject_type_t type, mach_port_mscount_t * mscount );
158 static void releasePortForObject( OSObject * obj,
159 ipc_kobject_type_t type );
160 static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type );
161
162 static OSDictionary * dictForType( ipc_kobject_type_t type );
163
164 static mach_port_name_t makeSendRightForTask( task_t task,
165 io_object_t obj, ipc_kobject_type_t type );
166
167 virtual void free();
168 };
169
170 #define super OSObject
171 OSDefineMetaClassAndStructors(IOMachPort, OSObject)
172
173 static IOLock * gIOObjectPortLock;
174
175 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
176
177 // not in dictForType() for debugging ease
178 static OSDictionary * gIOObjectPorts;
179 static OSDictionary * gIOConnectPorts;
180
181 OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
182 {
183 OSDictionary ** dict;
184
185 if( IKOT_IOKIT_OBJECT == type )
186 dict = &gIOObjectPorts;
187 else if( IKOT_IOKIT_CONNECT == type )
188 dict = &gIOConnectPorts;
189 else
190 return( 0 );
191
192 if( 0 == *dict)
193 *dict = OSDictionary::withCapacity( 1 );
194
195 return( *dict );
196 }
197
198 IOMachPort * IOMachPort::portForObject ( OSObject * obj,
199 ipc_kobject_type_t type )
200 {
201 IOMachPort * inst = 0;
202 OSDictionary * dict;
203
204 IOTakeLock( gIOObjectPortLock);
205
206 do {
207
208 dict = dictForType( type );
209 if( !dict)
210 continue;
211
212 if( (inst = (IOMachPort *)
213 dict->getObject( (const OSSymbol *) obj ))) {
214 inst->mscount++;
215 inst->retain();
216 continue;
217 }
218
219 inst = new IOMachPort;
220 if( inst && !inst->init()) {
221 inst = 0;
222 continue;
223 }
224
225 inst->port = iokit_alloc_object_port( obj, type );
226 if( inst->port) {
227 // retains obj
228 dict->setObject( (const OSSymbol *) obj, inst );
229 inst->mscount++;
230
231 } else {
232 inst->release();
233 inst = 0;
234 }
235
236 } while( false );
237
238 IOUnlock( gIOObjectPortLock);
239
240 return( inst );
241 }
242
243 bool IOMachPort::noMoreSendersForObject( OSObject * obj,
244 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
245 {
246 OSDictionary * dict;
247 IOMachPort * machPort;
248 bool destroyed = true;
249
250 IOTakeLock( gIOObjectPortLock);
251
252 if( (dict = dictForType( type ))) {
253 obj->retain();
254
255 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
256 if( machPort) {
257 destroyed = (machPort->mscount <= *mscount);
258 if( destroyed)
259 dict->removeObject( (const OSSymbol *) obj );
260 else
261 *mscount = machPort->mscount;
262 }
263 obj->release();
264 }
265
266 IOUnlock( gIOObjectPortLock);
267
268 return( destroyed );
269 }
270
271 void IOMachPort::releasePortForObject( OSObject * obj,
272 ipc_kobject_type_t type )
273 {
274 OSDictionary * dict;
275 IOMachPort * machPort;
276
277 IOTakeLock( gIOObjectPortLock);
278
279 if( (dict = dictForType( type ))) {
280 obj->retain();
281 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
282 if( machPort && !machPort->holdDestroy)
283 dict->removeObject( (const OSSymbol *) obj );
284 obj->release();
285 }
286
287 IOUnlock( gIOObjectPortLock);
288 }
289
290 void IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type )
291 {
292 OSDictionary * dict;
293 IOMachPort * machPort;
294
295 IOLockLock( gIOObjectPortLock );
296
297 if( (dict = dictForType( type ))) {
298 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
299 if( machPort)
300 machPort->holdDestroy = true;
301 }
302
303 IOLockUnlock( gIOObjectPortLock );
304 }
305
306 void IOUserClient::destroyUserReferences( OSObject * obj )
307 {
308 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
309
310 // panther, 3160200
311 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
312
313 OSDictionary * dict;
314
315 IOTakeLock( gIOObjectPortLock);
316 obj->retain();
317
318 if( (dict = IOMachPort::dictForType( IKOT_IOKIT_CONNECT )))
319 {
320 IOMachPort * port;
321 port = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
322 if (port)
323 {
324 IOUserClient * uc;
325 if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings)
326 {
327 dict->setObject((const OSSymbol *) uc->mappings, port);
328 iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
329
330 uc->mappings->release();
331 uc->mappings = 0;
332 }
333 dict->removeObject( (const OSSymbol *) obj );
334 }
335 }
336 obj->release();
337 IOUnlock( gIOObjectPortLock);
338 }
339
340 mach_port_name_t IOMachPort::makeSendRightForTask( task_t task,
341 io_object_t obj, ipc_kobject_type_t type )
342 {
343 return( iokit_make_send_right( task, obj, type ));
344 }
345
346 void IOMachPort::free( void )
347 {
348 if( port)
349 iokit_destroy_object_port( port );
350 super::free();
351 }
352
353 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
354
355 class IOUserNotification : public OSIterator
356 {
357 OSDeclareDefaultStructors(IOUserNotification)
358
359 IONotifier * holdNotify;
360 IOLock * lock;
361
362 public:
363
364 virtual bool init( void );
365 virtual void free();
366
367 virtual void setNotification( IONotifier * obj );
368
369 virtual void reset();
370 virtual bool isValid();
371 };
372
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374
375 extern "C" {
376
377 // functions called from osfmk/device/iokit_rpc.c
378
379 void
380 iokit_add_reference( io_object_t obj )
381 {
382 if( obj)
383 obj->retain();
384 }
385
386 void
387 iokit_remove_reference( io_object_t obj )
388 {
389 if( obj)
390 obj->release();
391 }
392
393 ipc_port_t
394 iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
395 {
396 IOMachPort * machPort;
397 ipc_port_t port;
398
399 if( (machPort = IOMachPort::portForObject( obj, type ))) {
400
401 port = machPort->port;
402 if( port)
403 iokit_retain_port( port );
404
405 machPort->release();
406
407 } else
408 port = NULL;
409
410 return( port );
411 }
412
413 kern_return_t
414 iokit_client_died( io_object_t obj, ipc_port_t /* port */,
415 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
416 {
417 IOUserClient * client;
418 IOMemoryMap * map;
419 IOUserNotification * notify;
420
421 if( !IOMachPort::noMoreSendersForObject( obj, type, mscount ))
422 return( kIOReturnNotReady );
423
424 if( IKOT_IOKIT_CONNECT == type)
425 {
426 if( (client = OSDynamicCast( IOUserClient, obj ))) {
427 IOStatisticsClientCall();
428 client->clientDied();
429 }
430 }
431 else if( IKOT_IOKIT_OBJECT == type)
432 {
433 if( (map = OSDynamicCast( IOMemoryMap, obj )))
434 map->taskDied();
435 else if( (notify = OSDynamicCast( IOUserNotification, obj )))
436 notify->setNotification( 0 );
437 }
438
439 return( kIOReturnSuccess );
440 }
441
442 }; /* extern "C" */
443
444 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
445
446 class IOServiceUserNotification : public IOUserNotification
447 {
448 OSDeclareDefaultStructors(IOServiceUserNotification)
449
450 struct PingMsg {
451 mach_msg_header_t msgHdr;
452 OSNotificationHeader64 notifyHeader;
453 };
454
455 enum { kMaxOutstanding = 1024 };
456
457 PingMsg * pingMsg;
458 vm_size_t msgSize;
459 OSArray * newSet;
460 OSObject * lastEntry;
461 bool armed;
462
463 public:
464
465 virtual bool init( mach_port_t port, natural_t type,
466 void * reference, vm_size_t referenceSize,
467 bool clientIs64 );
468 virtual void free();
469
470 static bool _handler( void * target,
471 void * ref, IOService * newService, IONotifier * notifier );
472 virtual bool handler( void * ref, IOService * newService );
473
474 virtual OSObject * getNextObject();
475 };
476
477 class IOServiceMessageUserNotification : public IOUserNotification
478 {
479 OSDeclareDefaultStructors(IOServiceMessageUserNotification)
480
481 struct PingMsg {
482 mach_msg_header_t msgHdr;
483 mach_msg_body_t msgBody;
484 mach_msg_port_descriptor_t ports[1];
485 OSNotificationHeader64 notifyHeader __attribute__ ((packed));
486 };
487
488 PingMsg * pingMsg;
489 vm_size_t msgSize;
490 uint8_t clientIs64;
491 int owningPID;
492
493 public:
494
495 virtual bool init( mach_port_t port, natural_t type,
496 void * reference, vm_size_t referenceSize,
497 vm_size_t extraSize,
498 bool clientIs64 );
499
500 virtual void free();
501
502 static IOReturn _handler( void * target, void * ref,
503 UInt32 messageType, IOService * provider,
504 void * messageArgument, vm_size_t argSize );
505 virtual IOReturn handler( void * ref,
506 UInt32 messageType, IOService * provider,
507 void * messageArgument, vm_size_t argSize );
508
509 virtual OSObject * getNextObject();
510 };
511
512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
513
514 #undef super
515 #define super OSIterator
516 OSDefineMetaClass( IOUserNotification, OSIterator )
517 OSDefineAbstractStructors( IOUserNotification, OSIterator )
518
519 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
520
521 bool IOUserNotification::init( void )
522 {
523 if( !super::init())
524 return( false );
525
526 lock = IOLockAlloc();
527 if( !lock)
528 return( false );
529
530 return( true );
531 }
532
533 void IOUserNotification::free( void )
534 {
535 if( holdNotify)
536 holdNotify->remove();
537 // can't be in handler now
538
539 if( lock)
540 IOLockFree( lock );
541
542 super::free();
543 }
544
545
546 void IOUserNotification::setNotification( IONotifier * notify )
547 {
548 IONotifier * previousNotify;
549
550 IOLockLock( gIOObjectPortLock);
551
552 previousNotify = holdNotify;
553 holdNotify = notify;
554
555 IOLockUnlock( gIOObjectPortLock);
556
557 if( previousNotify)
558 previousNotify->remove();
559 }
560
561 void IOUserNotification::reset()
562 {
563 // ?
564 }
565
566 bool IOUserNotification::isValid()
567 {
568 return( true );
569 }
570
571 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
572
573 #undef super
574 #define super IOUserNotification
575 OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
576
577 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
578
579 bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
580 void * reference, vm_size_t referenceSize,
581 bool clientIs64 )
582 {
583 if( !super::init())
584 return( false );
585
586 newSet = OSArray::withCapacity( 1 );
587 if( !newSet)
588 return( false );
589
590 if (referenceSize > sizeof(OSAsyncReference64))
591 return( false );
592
593 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
594 pingMsg = (PingMsg *) IOMalloc( msgSize);
595 if( !pingMsg)
596 return( false );
597
598 bzero( pingMsg, msgSize);
599
600 pingMsg->msgHdr.msgh_remote_port = port;
601 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS(
602 MACH_MSG_TYPE_COPY_SEND /*remote*/,
603 MACH_MSG_TYPE_MAKE_SEND /*local*/);
604 pingMsg->msgHdr.msgh_size = msgSize;
605 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
606
607 pingMsg->notifyHeader.size = 0;
608 pingMsg->notifyHeader.type = type;
609 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
610
611 return( true );
612 }
613
614 void IOServiceUserNotification::free( void )
615 {
616 PingMsg * _pingMsg;
617 vm_size_t _msgSize;
618 OSArray * _newSet;
619 OSObject * _lastEntry;
620
621 _pingMsg = pingMsg;
622 _msgSize = msgSize;
623 _lastEntry = lastEntry;
624 _newSet = newSet;
625
626 super::free();
627
628 if( _pingMsg && _msgSize) {
629 if (_pingMsg->msgHdr.msgh_remote_port) {
630 iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
631 }
632 IOFree(_pingMsg, _msgSize);
633 }
634
635 if( _lastEntry)
636 _lastEntry->release();
637
638 if( _newSet)
639 _newSet->release();
640 }
641
642 bool IOServiceUserNotification::_handler( void * target,
643 void * ref, IOService * newService, IONotifier * notifier )
644 {
645 return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
646 }
647
648 bool IOServiceUserNotification::handler( void * ref,
649 IOService * newService )
650 {
651 unsigned int count;
652 kern_return_t kr;
653 ipc_port_t port = NULL;
654 bool sendPing = false;
655
656 IOTakeLock( lock );
657
658 count = newSet->getCount();
659 if( count < kMaxOutstanding) {
660
661 newSet->setObject( newService );
662 if( (sendPing = (armed && (0 == count))))
663 armed = false;
664 }
665
666 IOUnlock( lock );
667
668 if( kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type)
669 IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT );
670
671 if( sendPing) {
672 if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) ))
673 pingMsg->msgHdr.msgh_local_port = port;
674 else
675 pingMsg->msgHdr.msgh_local_port = NULL;
676
677 kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
678 pingMsg->msgHdr.msgh_size);
679 if( port)
680 iokit_release_port( port );
681
682 if( KERN_SUCCESS != kr)
683 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
684 }
685
686 return( true );
687 }
688
689 OSObject * IOServiceUserNotification::getNextObject()
690 {
691 unsigned int count;
692 OSObject * result;
693
694 IOTakeLock( lock );
695
696 if( lastEntry)
697 lastEntry->release();
698
699 count = newSet->getCount();
700 if( count ) {
701 result = newSet->getObject( count - 1 );
702 result->retain();
703 newSet->removeObject( count - 1);
704 } else {
705 result = 0;
706 armed = true;
707 }
708 lastEntry = result;
709
710 IOUnlock( lock );
711
712 return( result );
713 }
714
715 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
716
717 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
718
719 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
720
721 bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
722 void * reference, vm_size_t referenceSize, vm_size_t extraSize,
723 bool client64 )
724 {
725 if( !super::init())
726 return( false );
727
728 if (referenceSize > sizeof(OSAsyncReference64))
729 return( false );
730
731 clientIs64 = client64;
732
733 owningPID = proc_selfpid();
734
735 extraSize += sizeof(IOServiceInterestContent64);
736 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize + extraSize;
737 pingMsg = (PingMsg *) IOMalloc( msgSize);
738 if( !pingMsg)
739 return( false );
740
741 bzero( pingMsg, msgSize);
742
743 pingMsg->msgHdr.msgh_remote_port = port;
744 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS_COMPLEX
745 | MACH_MSGH_BITS(
746 MACH_MSG_TYPE_COPY_SEND /*remote*/,
747 MACH_MSG_TYPE_MAKE_SEND /*local*/);
748 pingMsg->msgHdr.msgh_size = msgSize;
749 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
750
751 pingMsg->msgBody.msgh_descriptor_count = 1;
752
753 pingMsg->ports[0].name = 0;
754 pingMsg->ports[0].disposition = MACH_MSG_TYPE_MAKE_SEND;
755 pingMsg->ports[0].type = MACH_MSG_PORT_DESCRIPTOR;
756
757 pingMsg->notifyHeader.size = extraSize;
758 pingMsg->notifyHeader.type = type;
759 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
760
761 return( true );
762 }
763
764 void IOServiceMessageUserNotification::free( void )
765 {
766 PingMsg * _pingMsg;
767 vm_size_t _msgSize;
768
769 _pingMsg = pingMsg;
770 _msgSize = msgSize;
771
772 super::free();
773
774 if( _pingMsg && _msgSize) {
775 if (_pingMsg->msgHdr.msgh_remote_port) {
776 iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
777 }
778 IOFree( _pingMsg, _msgSize);
779 }
780 }
781
782 IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
783 UInt32 messageType, IOService * provider,
784 void * argument, vm_size_t argSize )
785 {
786 return( ((IOServiceMessageUserNotification *) target)->handler(
787 ref, messageType, provider, argument, argSize));
788 }
789
790 IOReturn IOServiceMessageUserNotification::handler( void * ref,
791 UInt32 messageType, IOService * provider,
792 void * messageArgument, vm_size_t argSize )
793 {
794 kern_return_t kr;
795 ipc_port_t thisPort, providerPort;
796 IOServiceInterestContent64 * data = (IOServiceInterestContent64 *)
797 ((((uint8_t *) pingMsg) + msgSize) - pingMsg->notifyHeader.size);
798 // == pingMsg->notifyHeader.content;
799
800 if (kIOMessageCopyClientID == messageType)
801 {
802 *((void **) messageArgument) = OSNumber::withNumber(owningPID, 32);
803 return (kIOReturnSuccess);
804 }
805
806 data->messageType = messageType;
807
808 if( argSize == 0)
809 {
810 data->messageArgument[0] = (io_user_reference_t) messageArgument;
811 if (clientIs64)
812 argSize = sizeof(data->messageArgument[0]);
813 else
814 {
815 data->messageArgument[0] |= (data->messageArgument[0] << 32);
816 argSize = sizeof(uint32_t);
817 }
818 }
819 else
820 {
821 if( argSize > kIOUserNotifyMaxMessageSize)
822 argSize = kIOUserNotifyMaxMessageSize;
823 bcopy( messageArgument, data->messageArgument, argSize );
824 }
825 pingMsg->msgHdr.msgh_size = msgSize - pingMsg->notifyHeader.size
826 + sizeof( IOServiceInterestContent64 )
827 - sizeof( data->messageArgument)
828 + argSize;
829
830 providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
831 pingMsg->ports[0].name = providerPort;
832 thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
833 pingMsg->msgHdr.msgh_local_port = thisPort;
834 kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
835 pingMsg->msgHdr.msgh_size);
836 if( thisPort)
837 iokit_release_port( thisPort );
838 if( providerPort)
839 iokit_release_port( providerPort );
840
841 if( KERN_SUCCESS != kr)
842 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
843
844 return( kIOReturnSuccess );
845 }
846
847 OSObject * IOServiceMessageUserNotification::getNextObject()
848 {
849 return( 0 );
850 }
851
852 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
853
854 #undef super
855 #define super IOService
856 OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
857
858 void IOUserClient::initialize( void )
859 {
860 gIOObjectPortLock = IOLockAlloc();
861
862 assert( gIOObjectPortLock );
863 }
864
865 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
866 mach_port_t wakePort,
867 void *callback, void *refcon)
868 {
869 asyncRef[kIOAsyncReservedIndex] = ((uintptr_t) wakePort)
870 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
871 asyncRef[kIOAsyncCalloutFuncIndex] = (uintptr_t) callback;
872 asyncRef[kIOAsyncCalloutRefconIndex] = (uintptr_t) refcon;
873 }
874
875 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
876 mach_port_t wakePort,
877 mach_vm_address_t callback, io_user_reference_t refcon)
878 {
879 asyncRef[kIOAsyncReservedIndex] = ((io_user_reference_t) wakePort)
880 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
881 asyncRef[kIOAsyncCalloutFuncIndex] = (io_user_reference_t) callback;
882 asyncRef[kIOAsyncCalloutRefconIndex] = refcon;
883 }
884
885 static OSDictionary * CopyConsoleUser(UInt32 uid)
886 {
887 OSArray * array;
888 OSDictionary * user = 0;
889
890 if ((array = OSDynamicCast(OSArray,
891 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
892 {
893 for (unsigned int idx = 0;
894 (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
895 idx++) {
896 OSNumber * num;
897
898 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
899 && (uid == num->unsigned32BitValue())) {
900 user->retain();
901 break;
902 }
903 }
904 array->release();
905 }
906 return user;
907 }
908
909 static OSDictionary * CopyUserOnConsole(void)
910 {
911 OSArray * array;
912 OSDictionary * user = 0;
913
914 if ((array = OSDynamicCast(OSArray,
915 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
916 {
917 for (unsigned int idx = 0;
918 (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
919 idx++)
920 {
921 if (kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
922 {
923 user->retain();
924 break;
925 }
926 }
927 array->release();
928 }
929 return (user);
930 }
931
932 IOReturn IOUserClient::clientHasPrivilege( void * securityToken,
933 const char * privilegeName )
934 {
935 kern_return_t kr;
936 security_token_t token;
937 mach_msg_type_number_t count;
938 task_t task;
939 OSDictionary * user;
940 bool secureConsole;
941
942
943 if (!strncmp(privilegeName, kIOClientPrivilegeForeground,
944 sizeof(kIOClientPrivilegeForeground)))
945 {
946 /* is graphics access denied for current task? */
947 if (proc_get_task_selfgpuacc_deny() != 0)
948 return (kIOReturnNotPrivileged);
949 else
950 return (kIOReturnSuccess);
951 }
952
953 if (!strncmp(privilegeName, kIOClientPrivilegeConsoleSession,
954 sizeof(kIOClientPrivilegeConsoleSession)))
955 {
956 kauth_cred_t cred;
957 proc_t p;
958
959 task = (task_t) securityToken;
960 if (!task)
961 task = current_task();
962 p = (proc_t) get_bsdtask_info(task);
963 kr = kIOReturnNotPrivileged;
964
965 if (p && (cred = kauth_cred_proc_ref(p)))
966 {
967 user = CopyUserOnConsole();
968 if (user)
969 {
970 OSNumber * num;
971 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionAuditIDKey)))
972 && (cred->cr_audit.as_aia_p->ai_asid == (au_asid_t) num->unsigned32BitValue()))
973 {
974 kr = kIOReturnSuccess;
975 }
976 user->release();
977 }
978 kauth_cred_unref(&cred);
979 }
980 return (kr);
981 }
982
983 if ((secureConsole = !strncmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess,
984 sizeof(kIOClientPrivilegeSecureConsoleProcess))))
985 task = (task_t)((IOUCProcessToken *)securityToken)->token;
986 else
987 task = (task_t)securityToken;
988
989 count = TASK_SECURITY_TOKEN_COUNT;
990 kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count );
991
992 if (KERN_SUCCESS != kr)
993 {}
994 else if (!strncmp(privilegeName, kIOClientPrivilegeAdministrator,
995 sizeof(kIOClientPrivilegeAdministrator))) {
996 if (0 != token.val[0])
997 kr = kIOReturnNotPrivileged;
998 } else if (!strncmp(privilegeName, kIOClientPrivilegeLocalUser,
999 sizeof(kIOClientPrivilegeLocalUser))) {
1000 user = CopyConsoleUser(token.val[0]);
1001 if ( user )
1002 user->release();
1003 else
1004 kr = kIOReturnNotPrivileged;
1005 } else if (secureConsole || !strncmp(privilegeName, kIOClientPrivilegeConsoleUser,
1006 sizeof(kIOClientPrivilegeConsoleUser))) {
1007 user = CopyConsoleUser(token.val[0]);
1008 if ( user ) {
1009 if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue)
1010 kr = kIOReturnNotPrivileged;
1011 else if ( secureConsole ) {
1012 OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey));
1013 if ( pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid)
1014 kr = kIOReturnNotPrivileged;
1015 }
1016 user->release();
1017 }
1018 else
1019 kr = kIOReturnNotPrivileged;
1020 } else
1021 kr = kIOReturnUnsupported;
1022
1023 return (kr);
1024 }
1025
1026 bool IOUserClient::init()
1027 {
1028 if (getPropertyTable() || super::init())
1029 return reserve();
1030
1031 return false;
1032 }
1033
1034 bool IOUserClient::init(OSDictionary * dictionary)
1035 {
1036 if (getPropertyTable() || super::init(dictionary))
1037 return reserve();
1038
1039 return false;
1040 }
1041
1042 bool IOUserClient::initWithTask(task_t owningTask,
1043 void * securityID,
1044 UInt32 type )
1045 {
1046 if (getPropertyTable() || super::init())
1047 return reserve();
1048
1049 return false;
1050 }
1051
1052 bool IOUserClient::initWithTask(task_t owningTask,
1053 void * securityID,
1054 UInt32 type,
1055 OSDictionary * properties )
1056 {
1057 bool ok;
1058
1059 ok = super::init( properties );
1060 ok &= initWithTask( owningTask, securityID, type );
1061
1062 return( ok );
1063 }
1064
1065 bool IOUserClient::reserve()
1066 {
1067 if(!reserved) {
1068 reserved = IONew(ExpansionData, 1);
1069 if (!reserved) {
1070 return false;
1071 }
1072 }
1073
1074 IOStatisticsRegisterCounter();
1075
1076 return true;
1077 }
1078
1079 void IOUserClient::free()
1080 {
1081 if( mappings)
1082 mappings->release();
1083
1084 IOStatisticsUnregisterCounter();
1085
1086 if (reserved)
1087 IODelete(reserved, ExpansionData, 1);
1088
1089 super::free();
1090 }
1091
1092 IOReturn IOUserClient::clientDied( void )
1093 {
1094 return( clientClose());
1095 }
1096
1097 IOReturn IOUserClient::clientClose( void )
1098 {
1099 return( kIOReturnUnsupported );
1100 }
1101
1102 IOService * IOUserClient::getService( void )
1103 {
1104 return( 0 );
1105 }
1106
1107 IOReturn IOUserClient::registerNotificationPort(
1108 mach_port_t /* port */,
1109 UInt32 /* type */,
1110 UInt32 /* refCon */)
1111 {
1112 return( kIOReturnUnsupported);
1113 }
1114
1115 IOReturn IOUserClient::registerNotificationPort(
1116 mach_port_t port,
1117 UInt32 type,
1118 io_user_reference_t refCon)
1119 {
1120 return (registerNotificationPort(port, type, (UInt32) refCon));
1121 }
1122
1123 IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
1124 semaphore_t * semaphore )
1125 {
1126 return( kIOReturnUnsupported);
1127 }
1128
1129 IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
1130 {
1131 return( kIOReturnUnsupported);
1132 }
1133
1134 IOReturn IOUserClient::clientMemoryForType( UInt32 type,
1135 IOOptionBits * options,
1136 IOMemoryDescriptor ** memory )
1137 {
1138 return( kIOReturnUnsupported);
1139 }
1140
1141 #if !__LP64__
1142 IOMemoryMap * IOUserClient::mapClientMemory(
1143 IOOptionBits type,
1144 task_t task,
1145 IOOptionBits mapFlags,
1146 IOVirtualAddress atAddress )
1147 {
1148 return (NULL);
1149 }
1150 #endif
1151
1152 IOMemoryMap * IOUserClient::mapClientMemory64(
1153 IOOptionBits type,
1154 task_t task,
1155 IOOptionBits mapFlags,
1156 mach_vm_address_t atAddress )
1157 {
1158 IOReturn err;
1159 IOOptionBits options = 0;
1160 IOMemoryDescriptor * memory;
1161 IOMemoryMap * map = 0;
1162
1163 err = clientMemoryForType( (UInt32) type, &options, &memory );
1164
1165 if( memory && (kIOReturnSuccess == err)) {
1166
1167 options = (options & ~kIOMapUserOptionsMask)
1168 | (mapFlags & kIOMapUserOptionsMask);
1169 map = memory->createMappingInTask( task, atAddress, options );
1170 memory->release();
1171 }
1172
1173 return( map );
1174 }
1175
1176 IOReturn IOUserClient::exportObjectToClient(task_t task,
1177 OSObject *obj, io_object_t *clientObj)
1178 {
1179 mach_port_name_t name;
1180
1181 name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
1182 assert( name );
1183
1184 *(mach_port_name_t *)clientObj = name;
1185 return kIOReturnSuccess;
1186 }
1187
1188 IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
1189 {
1190 return( 0 );
1191 }
1192
1193 IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
1194 {
1195 return( 0 );
1196 }
1197
1198 IOExternalMethod * IOUserClient::
1199 getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
1200 {
1201 IOExternalMethod *method = getExternalMethodForIndex(index);
1202
1203 if (method)
1204 *targetP = (IOService *) method->object;
1205
1206 return method;
1207 }
1208
1209 IOExternalAsyncMethod * IOUserClient::
1210 getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
1211 {
1212 IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
1213
1214 if (method)
1215 *targetP = (IOService *) method->object;
1216
1217 return method;
1218 }
1219
1220 IOExternalTrap * IOUserClient::
1221 getExternalTrapForIndex(UInt32 index)
1222 {
1223 return NULL;
1224 }
1225
1226 IOExternalTrap * IOUserClient::
1227 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
1228 {
1229 IOExternalTrap *trap = getExternalTrapForIndex(index);
1230
1231 if (trap) {
1232 *targetP = trap->object;
1233 }
1234
1235 return trap;
1236 }
1237
1238 IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
1239 {
1240 mach_port_t port;
1241 port = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
1242
1243 if (MACH_PORT_NULL != port)
1244 iokit_release_port_send(port);
1245
1246 return (kIOReturnSuccess);
1247 }
1248
1249 IOReturn IOUserClient::releaseNotificationPort(mach_port_t port)
1250 {
1251 if (MACH_PORT_NULL != port)
1252 iokit_release_port_send(port);
1253
1254 return (kIOReturnSuccess);
1255 }
1256
1257 IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
1258 IOReturn result, void *args[], UInt32 numArgs)
1259 {
1260 OSAsyncReference64 reference64;
1261 io_user_reference_t args64[kMaxAsyncArgs];
1262 unsigned int idx;
1263
1264 if (numArgs > kMaxAsyncArgs)
1265 return kIOReturnMessageTooLarge;
1266
1267 for (idx = 0; idx < kOSAsyncRef64Count; idx++)
1268 reference64[idx] = REF64(reference[idx]);
1269
1270 for (idx = 0; idx < numArgs; idx++)
1271 args64[idx] = REF64(args[idx]);
1272
1273 return (sendAsyncResult64(reference64, result, args64, numArgs));
1274 }
1275
1276 IOReturn IOUserClient::sendAsyncResult64(OSAsyncReference64 reference,
1277 IOReturn result, io_user_reference_t args[], UInt32 numArgs)
1278 {
1279 struct ReplyMsg
1280 {
1281 mach_msg_header_t msgHdr;
1282 union
1283 {
1284 struct
1285 {
1286 OSNotificationHeader notifyHdr;
1287 IOAsyncCompletionContent asyncContent;
1288 uint32_t args[kMaxAsyncArgs];
1289 } msg32;
1290 struct
1291 {
1292 OSNotificationHeader64 notifyHdr;
1293 IOAsyncCompletionContent asyncContent;
1294 io_user_reference_t args[kMaxAsyncArgs] __attribute__ ((packed));
1295 } msg64;
1296 } m;
1297 };
1298 ReplyMsg replyMsg;
1299 mach_port_t replyPort;
1300 kern_return_t kr;
1301
1302 // If no reply port, do nothing.
1303 replyPort = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
1304 if (replyPort == MACH_PORT_NULL)
1305 return kIOReturnSuccess;
1306
1307 if (numArgs > kMaxAsyncArgs)
1308 return kIOReturnMessageTooLarge;
1309
1310 replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
1311 0 /*local*/);
1312 replyMsg.msgHdr.msgh_remote_port = replyPort;
1313 replyMsg.msgHdr.msgh_local_port = 0;
1314 replyMsg.msgHdr.msgh_id = kOSNotificationMessageID;
1315 if (kIOUCAsync64Flag & reference[0])
1316 {
1317 replyMsg.msgHdr.msgh_size =
1318 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg64)
1319 - (kMaxAsyncArgs - numArgs) * sizeof(io_user_reference_t);
1320 replyMsg.m.msg64.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1321 + numArgs * sizeof(io_user_reference_t);
1322 replyMsg.m.msg64.notifyHdr.type = kIOAsyncCompletionNotificationType;
1323 bcopy(reference, replyMsg.m.msg64.notifyHdr.reference, sizeof(OSAsyncReference64));
1324
1325 replyMsg.m.msg64.asyncContent.result = result;
1326 if (numArgs)
1327 bcopy(args, replyMsg.m.msg64.args, numArgs * sizeof(io_user_reference_t));
1328 }
1329 else
1330 {
1331 unsigned int idx;
1332
1333 replyMsg.msgHdr.msgh_size =
1334 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg32)
1335 - (kMaxAsyncArgs - numArgs) * sizeof(uint32_t);
1336
1337 replyMsg.m.msg32.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1338 + numArgs * sizeof(uint32_t);
1339 replyMsg.m.msg32.notifyHdr.type = kIOAsyncCompletionNotificationType;
1340
1341 for (idx = 0; idx < kOSAsyncRefCount; idx++)
1342 replyMsg.m.msg32.notifyHdr.reference[idx] = REF32(reference[idx]);
1343
1344 replyMsg.m.msg32.asyncContent.result = result;
1345
1346 for (idx = 0; idx < numArgs; idx++)
1347 replyMsg.m.msg32.args[idx] = REF32(args[idx]);
1348 }
1349
1350 kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
1351 replyMsg.msgHdr.msgh_size);
1352 if( KERN_SUCCESS != kr)
1353 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
1354 return kr;
1355 }
1356
1357
1358 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1359
1360 extern "C" {
1361
1362 #define CHECK(cls,obj,out) \
1363 cls * out; \
1364 if( !(out = OSDynamicCast( cls, obj))) \
1365 return( kIOReturnBadArgument )
1366
1367 /* Routine io_object_get_class */
1368 kern_return_t is_io_object_get_class(
1369 io_object_t object,
1370 io_name_t className )
1371 {
1372 const OSMetaClass* my_obj = NULL;
1373
1374 if( !object)
1375 return( kIOReturnBadArgument );
1376
1377 my_obj = object->getMetaClass();
1378 if (!my_obj) {
1379 return (kIOReturnNotFound);
1380 }
1381
1382 strlcpy( className, my_obj->getClassName(), sizeof(io_name_t));
1383 return( kIOReturnSuccess );
1384 }
1385
1386 /* Routine io_object_get_superclass */
1387 kern_return_t is_io_object_get_superclass(
1388 mach_port_t master_port,
1389 io_name_t obj_name,
1390 io_name_t class_name)
1391 {
1392 const OSMetaClass* my_obj = NULL;
1393 const OSMetaClass* superclass = NULL;
1394 const OSSymbol *my_name = NULL;
1395 const char *my_cstr = NULL;
1396
1397 if (!obj_name || !class_name)
1398 return (kIOReturnBadArgument);
1399
1400 if( master_port != master_device_port)
1401 return( kIOReturnNotPrivileged);
1402
1403 my_name = OSSymbol::withCString(obj_name);
1404
1405 if (my_name) {
1406 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1407 my_name->release();
1408 }
1409 if (my_obj) {
1410 superclass = my_obj->getSuperClass();
1411 }
1412
1413 if (!superclass) {
1414 return( kIOReturnNotFound );
1415 }
1416
1417 my_cstr = superclass->getClassName();
1418
1419 if (my_cstr) {
1420 strlcpy(class_name, my_cstr, sizeof(io_name_t));
1421 return( kIOReturnSuccess );
1422 }
1423 return (kIOReturnNotFound);
1424 }
1425
1426 /* Routine io_object_get_bundle_identifier */
1427 kern_return_t is_io_object_get_bundle_identifier(
1428 mach_port_t master_port,
1429 io_name_t obj_name,
1430 io_name_t bundle_name)
1431 {
1432 const OSMetaClass* my_obj = NULL;
1433 const OSSymbol *my_name = NULL;
1434 const OSSymbol *identifier = NULL;
1435 const char *my_cstr = NULL;
1436
1437 if (!obj_name || !bundle_name)
1438 return (kIOReturnBadArgument);
1439
1440 if( master_port != master_device_port)
1441 return( kIOReturnNotPrivileged);
1442
1443 my_name = OSSymbol::withCString(obj_name);
1444
1445 if (my_name) {
1446 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1447 my_name->release();
1448 }
1449
1450 if (my_obj) {
1451 identifier = my_obj->getKmodName();
1452 }
1453 if (!identifier) {
1454 return( kIOReturnNotFound );
1455 }
1456
1457 my_cstr = identifier->getCStringNoCopy();
1458 if (my_cstr) {
1459 strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
1460 return( kIOReturnSuccess );
1461 }
1462
1463 return (kIOReturnBadArgument);
1464 }
1465
1466 /* Routine io_object_conforms_to */
1467 kern_return_t is_io_object_conforms_to(
1468 io_object_t object,
1469 io_name_t className,
1470 boolean_t *conforms )
1471 {
1472 if( !object)
1473 return( kIOReturnBadArgument );
1474
1475 *conforms = (0 != object->metaCast( className ));
1476 return( kIOReturnSuccess );
1477 }
1478
1479 /* Routine io_object_get_retain_count */
1480 kern_return_t is_io_object_get_retain_count(
1481 io_object_t object,
1482 uint32_t *retainCount )
1483 {
1484 if( !object)
1485 return( kIOReturnBadArgument );
1486
1487 *retainCount = object->getRetainCount();
1488 return( kIOReturnSuccess );
1489 }
1490
1491 /* Routine io_iterator_next */
1492 kern_return_t is_io_iterator_next(
1493 io_object_t iterator,
1494 io_object_t *object )
1495 {
1496 OSObject * obj;
1497
1498 CHECK( OSIterator, iterator, iter );
1499
1500 obj = iter->getNextObject();
1501 if( obj) {
1502 obj->retain();
1503 *object = obj;
1504 return( kIOReturnSuccess );
1505 } else
1506 return( kIOReturnNoDevice );
1507 }
1508
1509 /* Routine io_iterator_reset */
1510 kern_return_t is_io_iterator_reset(
1511 io_object_t iterator )
1512 {
1513 CHECK( OSIterator, iterator, iter );
1514
1515 iter->reset();
1516
1517 return( kIOReturnSuccess );
1518 }
1519
1520 /* Routine io_iterator_is_valid */
1521 kern_return_t is_io_iterator_is_valid(
1522 io_object_t iterator,
1523 boolean_t *is_valid )
1524 {
1525 CHECK( OSIterator, iterator, iter );
1526
1527 *is_valid = iter->isValid();
1528
1529 return( kIOReturnSuccess );
1530 }
1531
1532 /* Routine io_service_match_property_table */
1533 kern_return_t is_io_service_match_property_table(
1534 io_service_t _service,
1535 io_string_t matching,
1536 boolean_t *matches )
1537 {
1538 CHECK( IOService, _service, service );
1539
1540 kern_return_t kr;
1541 OSObject * obj;
1542 OSDictionary * dict;
1543
1544 obj = OSUnserializeXML( matching );
1545
1546 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1547 *matches = service->passiveMatch( dict );
1548 kr = kIOReturnSuccess;
1549 } else
1550 kr = kIOReturnBadArgument;
1551
1552 if( obj)
1553 obj->release();
1554
1555 return( kr );
1556 }
1557
1558 /* Routine io_service_match_property_table_ool */
1559 kern_return_t is_io_service_match_property_table_ool(
1560 io_object_t service,
1561 io_buf_ptr_t matching,
1562 mach_msg_type_number_t matchingCnt,
1563 kern_return_t *result,
1564 boolean_t *matches )
1565 {
1566 kern_return_t kr;
1567 vm_offset_t data;
1568 vm_map_offset_t map_data;
1569
1570 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1571 data = CAST_DOWN(vm_offset_t, map_data);
1572
1573 if( KERN_SUCCESS == kr) {
1574 // must return success after vm_map_copyout() succeeds
1575 *result = is_io_service_match_property_table( service,
1576 (char *) data, matches );
1577 vm_deallocate( kernel_map, data, matchingCnt );
1578 }
1579
1580 return( kr );
1581 }
1582
1583 /* Routine io_service_get_matching_services */
1584 kern_return_t is_io_service_get_matching_services(
1585 mach_port_t master_port,
1586 io_string_t matching,
1587 io_iterator_t *existing )
1588 {
1589 kern_return_t kr;
1590 OSObject * obj;
1591 OSDictionary * dict;
1592
1593 if( master_port != master_device_port)
1594 return( kIOReturnNotPrivileged);
1595
1596 obj = OSUnserializeXML( matching );
1597
1598 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1599 *existing = IOService::getMatchingServices( dict );
1600 kr = kIOReturnSuccess;
1601 } else
1602 kr = kIOReturnBadArgument;
1603
1604 if( obj)
1605 obj->release();
1606
1607 return( kr );
1608 }
1609
1610 /* Routine io_service_get_matching_services_ool */
1611 kern_return_t is_io_service_get_matching_services_ool(
1612 mach_port_t master_port,
1613 io_buf_ptr_t matching,
1614 mach_msg_type_number_t matchingCnt,
1615 kern_return_t *result,
1616 io_object_t *existing )
1617 {
1618 kern_return_t kr;
1619 vm_offset_t data;
1620 vm_map_offset_t map_data;
1621
1622 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1623 data = CAST_DOWN(vm_offset_t, map_data);
1624
1625 if( KERN_SUCCESS == kr) {
1626 // must return success after vm_map_copyout() succeeds
1627 *result = is_io_service_get_matching_services( master_port,
1628 (char *) data, existing );
1629 vm_deallocate( kernel_map, data, matchingCnt );
1630 }
1631
1632 return( kr );
1633 }
1634
1635
1636 /* Routine io_service_get_matching_service */
1637 kern_return_t is_io_service_get_matching_service(
1638 mach_port_t master_port,
1639 io_string_t matching,
1640 io_service_t *service )
1641 {
1642 kern_return_t kr;
1643 OSObject * obj;
1644 OSDictionary * dict;
1645
1646 if( master_port != master_device_port)
1647 return( kIOReturnNotPrivileged);
1648
1649 obj = OSUnserializeXML( matching );
1650
1651 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1652 *service = IOService::copyMatchingService( dict );
1653 kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
1654 } else
1655 kr = kIOReturnBadArgument;
1656
1657 if( obj)
1658 obj->release();
1659
1660 return( kr );
1661 }
1662
1663 /* Routine io_service_get_matching_services_ool */
1664 kern_return_t is_io_service_get_matching_service_ool(
1665 mach_port_t master_port,
1666 io_buf_ptr_t matching,
1667 mach_msg_type_number_t matchingCnt,
1668 kern_return_t *result,
1669 io_object_t *service )
1670 {
1671 kern_return_t kr;
1672 vm_offset_t data;
1673 vm_map_offset_t map_data;
1674
1675 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1676 data = CAST_DOWN(vm_offset_t, map_data);
1677
1678 if( KERN_SUCCESS == kr) {
1679 // must return success after vm_map_copyout() succeeds
1680 *result = is_io_service_get_matching_service( master_port,
1681 (char *) data, service );
1682 vm_deallocate( kernel_map, data, matchingCnt );
1683 }
1684
1685 return( kr );
1686 }
1687
1688
1689 static kern_return_t internal_io_service_add_notification(
1690 mach_port_t master_port,
1691 io_name_t notification_type,
1692 io_string_t matching,
1693 mach_port_t port,
1694 void * reference,
1695 vm_size_t referenceSize,
1696 bool client64,
1697 io_object_t * notification )
1698 {
1699 IOServiceUserNotification * userNotify = 0;
1700 IONotifier * notify = 0;
1701 const OSSymbol * sym;
1702 OSDictionary * dict;
1703 IOReturn err;
1704 unsigned long int userMsgType;
1705
1706
1707 if( master_port != master_device_port)
1708 return( kIOReturnNotPrivileged);
1709
1710 do {
1711 err = kIOReturnNoResources;
1712
1713 if( !(sym = OSSymbol::withCString( notification_type )))
1714 err = kIOReturnNoResources;
1715
1716 if( !(dict = OSDynamicCast( OSDictionary,
1717 OSUnserializeXML( matching )))) {
1718 err = kIOReturnBadArgument;
1719 continue;
1720 }
1721
1722 if( (sym == gIOPublishNotification)
1723 || (sym == gIOFirstPublishNotification))
1724 userMsgType = kIOServicePublishNotificationType;
1725 else if( (sym == gIOMatchedNotification)
1726 || (sym == gIOFirstMatchNotification))
1727 userMsgType = kIOServiceMatchedNotificationType;
1728 else if( sym == gIOTerminatedNotification)
1729 userMsgType = kIOServiceTerminatedNotificationType;
1730 else
1731 userMsgType = kLastIOKitNotificationType;
1732
1733 userNotify = new IOServiceUserNotification;
1734
1735 if( userNotify && !userNotify->init( port, userMsgType,
1736 reference, referenceSize, client64)) {
1737 iokit_release_port_send(port);
1738 userNotify->release();
1739 userNotify = 0;
1740 }
1741 if( !userNotify)
1742 continue;
1743
1744 notify = IOService::addMatchingNotification( sym, dict,
1745 &userNotify->_handler, userNotify );
1746 if( notify) {
1747 *notification = userNotify;
1748 userNotify->setNotification( notify );
1749 err = kIOReturnSuccess;
1750 } else
1751 err = kIOReturnUnsupported;
1752
1753 } while( false );
1754
1755 if( sym)
1756 sym->release();
1757 if( dict)
1758 dict->release();
1759
1760 return( err );
1761 }
1762
1763
1764 /* Routine io_service_add_notification */
1765 kern_return_t is_io_service_add_notification(
1766 mach_port_t master_port,
1767 io_name_t notification_type,
1768 io_string_t matching,
1769 mach_port_t port,
1770 io_async_ref_t reference,
1771 mach_msg_type_number_t referenceCnt,
1772 io_object_t * notification )
1773 {
1774 return (internal_io_service_add_notification(master_port, notification_type,
1775 matching, port, &reference[0], sizeof(io_async_ref_t),
1776 false, notification));
1777 }
1778
1779 /* Routine io_service_add_notification_64 */
1780 kern_return_t is_io_service_add_notification_64(
1781 mach_port_t master_port,
1782 io_name_t notification_type,
1783 io_string_t matching,
1784 mach_port_t wake_port,
1785 io_async_ref64_t reference,
1786 mach_msg_type_number_t referenceCnt,
1787 io_object_t *notification )
1788 {
1789 return (internal_io_service_add_notification(master_port, notification_type,
1790 matching, wake_port, &reference[0], sizeof(io_async_ref64_t),
1791 true, notification));
1792 }
1793
1794
1795 static kern_return_t internal_io_service_add_notification_ool(
1796 mach_port_t master_port,
1797 io_name_t notification_type,
1798 io_buf_ptr_t matching,
1799 mach_msg_type_number_t matchingCnt,
1800 mach_port_t wake_port,
1801 void * reference,
1802 vm_size_t referenceSize,
1803 bool client64,
1804 kern_return_t *result,
1805 io_object_t *notification )
1806 {
1807 kern_return_t kr;
1808 vm_offset_t data;
1809 vm_map_offset_t map_data;
1810
1811 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1812 data = CAST_DOWN(vm_offset_t, map_data);
1813
1814 if( KERN_SUCCESS == kr) {
1815 // must return success after vm_map_copyout() succeeds
1816 *result = internal_io_service_add_notification( master_port, notification_type,
1817 (char *) data, wake_port, reference, referenceSize, client64, notification );
1818 vm_deallocate( kernel_map, data, matchingCnt );
1819 }
1820
1821 return( kr );
1822 }
1823
1824 /* Routine io_service_add_notification_ool */
1825 kern_return_t is_io_service_add_notification_ool(
1826 mach_port_t master_port,
1827 io_name_t notification_type,
1828 io_buf_ptr_t matching,
1829 mach_msg_type_number_t matchingCnt,
1830 mach_port_t wake_port,
1831 io_async_ref_t reference,
1832 mach_msg_type_number_t referenceCnt,
1833 kern_return_t *result,
1834 io_object_t *notification )
1835 {
1836 return (internal_io_service_add_notification_ool(master_port, notification_type,
1837 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref_t),
1838 false, result, notification));
1839 }
1840
1841 /* Routine io_service_add_notification_ool_64 */
1842 kern_return_t is_io_service_add_notification_ool_64(
1843 mach_port_t master_port,
1844 io_name_t notification_type,
1845 io_buf_ptr_t matching,
1846 mach_msg_type_number_t matchingCnt,
1847 mach_port_t wake_port,
1848 io_async_ref64_t reference,
1849 mach_msg_type_number_t referenceCnt,
1850 kern_return_t *result,
1851 io_object_t *notification )
1852 {
1853 return (internal_io_service_add_notification_ool(master_port, notification_type,
1854 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref64_t),
1855 true, result, notification));
1856 }
1857
1858 /* Routine io_service_add_notification_old */
1859 kern_return_t is_io_service_add_notification_old(
1860 mach_port_t master_port,
1861 io_name_t notification_type,
1862 io_string_t matching,
1863 mach_port_t port,
1864 // for binary compatibility reasons, this must be natural_t for ILP32
1865 natural_t ref,
1866 io_object_t * notification )
1867 {
1868 return( is_io_service_add_notification( master_port, notification_type,
1869 matching, port, &ref, 1, notification ));
1870 }
1871
1872
1873 static kern_return_t internal_io_service_add_interest_notification(
1874 io_object_t _service,
1875 io_name_t type_of_interest,
1876 mach_port_t port,
1877 void * reference,
1878 vm_size_t referenceSize,
1879 bool client64,
1880 io_object_t * notification )
1881 {
1882
1883 IOServiceMessageUserNotification * userNotify = 0;
1884 IONotifier * notify = 0;
1885 const OSSymbol * sym;
1886 IOReturn err;
1887
1888 CHECK( IOService, _service, service );
1889
1890 err = kIOReturnNoResources;
1891 if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1892
1893 userNotify = new IOServiceMessageUserNotification;
1894
1895 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
1896 reference, referenceSize,
1897 kIOUserNotifyMaxMessageSize,
1898 client64 )) {
1899 iokit_release_port_send(port);
1900 userNotify->release();
1901 userNotify = 0;
1902 }
1903 if( !userNotify)
1904 continue;
1905
1906 notify = service->registerInterest( sym,
1907 &userNotify->_handler, userNotify );
1908 if( notify) {
1909 *notification = userNotify;
1910 userNotify->setNotification( notify );
1911 err = kIOReturnSuccess;
1912 } else
1913 err = kIOReturnUnsupported;
1914
1915 sym->release();
1916
1917 } while( false );
1918
1919 return( err );
1920 }
1921
1922 /* Routine io_service_add_message_notification */
1923 kern_return_t is_io_service_add_interest_notification(
1924 io_object_t service,
1925 io_name_t type_of_interest,
1926 mach_port_t port,
1927 io_async_ref_t reference,
1928 mach_msg_type_number_t referenceCnt,
1929 io_object_t * notification )
1930 {
1931 return (internal_io_service_add_interest_notification(service, type_of_interest,
1932 port, &reference[0], sizeof(io_async_ref_t), false, notification));
1933 }
1934
1935 /* Routine io_service_add_interest_notification_64 */
1936 kern_return_t is_io_service_add_interest_notification_64(
1937 io_object_t service,
1938 io_name_t type_of_interest,
1939 mach_port_t wake_port,
1940 io_async_ref64_t reference,
1941 mach_msg_type_number_t referenceCnt,
1942 io_object_t *notification )
1943 {
1944 return (internal_io_service_add_interest_notification(service, type_of_interest,
1945 wake_port, &reference[0], sizeof(io_async_ref64_t), true, notification));
1946 }
1947
1948
1949 /* Routine io_service_acknowledge_notification */
1950 kern_return_t is_io_service_acknowledge_notification(
1951 io_object_t _service,
1952 natural_t notify_ref,
1953 natural_t response )
1954 {
1955 CHECK( IOService, _service, service );
1956
1957 return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1958 (IOOptionBits) response ));
1959
1960 }
1961
1962 /* Routine io_connect_get_semaphore */
1963 kern_return_t is_io_connect_get_notification_semaphore(
1964 io_connect_t connection,
1965 natural_t notification_type,
1966 semaphore_t *semaphore )
1967 {
1968 CHECK( IOUserClient, connection, client );
1969
1970 IOStatisticsClientCall();
1971 return( client->getNotificationSemaphore( (UInt32) notification_type,
1972 semaphore ));
1973 }
1974
1975 /* Routine io_registry_get_root_entry */
1976 kern_return_t is_io_registry_get_root_entry(
1977 mach_port_t master_port,
1978 io_object_t *root )
1979 {
1980 IORegistryEntry * entry;
1981
1982 if( master_port != master_device_port)
1983 return( kIOReturnNotPrivileged);
1984
1985 entry = IORegistryEntry::getRegistryRoot();
1986 if( entry)
1987 entry->retain();
1988 *root = entry;
1989
1990 return( kIOReturnSuccess );
1991 }
1992
1993 /* Routine io_registry_create_iterator */
1994 kern_return_t is_io_registry_create_iterator(
1995 mach_port_t master_port,
1996 io_name_t plane,
1997 uint32_t options,
1998 io_object_t *iterator )
1999 {
2000 if( master_port != master_device_port)
2001 return( kIOReturnNotPrivileged);
2002
2003 *iterator = IORegistryIterator::iterateOver(
2004 IORegistryEntry::getPlane( plane ), options );
2005
2006 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
2007 }
2008
2009 /* Routine io_registry_entry_create_iterator */
2010 kern_return_t is_io_registry_entry_create_iterator(
2011 io_object_t registry_entry,
2012 io_name_t plane,
2013 uint32_t options,
2014 io_object_t *iterator )
2015 {
2016 CHECK( IORegistryEntry, registry_entry, entry );
2017
2018 *iterator = IORegistryIterator::iterateOver( entry,
2019 IORegistryEntry::getPlane( plane ), options );
2020
2021 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
2022 }
2023
2024 /* Routine io_registry_iterator_enter */
2025 kern_return_t is_io_registry_iterator_enter_entry(
2026 io_object_t iterator )
2027 {
2028 CHECK( IORegistryIterator, iterator, iter );
2029
2030 iter->enterEntry();
2031
2032 return( kIOReturnSuccess );
2033 }
2034
2035 /* Routine io_registry_iterator_exit */
2036 kern_return_t is_io_registry_iterator_exit_entry(
2037 io_object_t iterator )
2038 {
2039 bool didIt;
2040
2041 CHECK( IORegistryIterator, iterator, iter );
2042
2043 didIt = iter->exitEntry();
2044
2045 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
2046 }
2047
2048 /* Routine io_registry_entry_from_path */
2049 kern_return_t is_io_registry_entry_from_path(
2050 mach_port_t master_port,
2051 io_string_t path,
2052 io_object_t *registry_entry )
2053 {
2054 IORegistryEntry * entry;
2055
2056 if( master_port != master_device_port)
2057 return( kIOReturnNotPrivileged);
2058
2059 entry = IORegistryEntry::fromPath( path );
2060
2061 *registry_entry = entry;
2062
2063 return( kIOReturnSuccess );
2064 }
2065
2066 /* Routine io_registry_entry_in_plane */
2067 kern_return_t is_io_registry_entry_in_plane(
2068 io_object_t registry_entry,
2069 io_name_t plane,
2070 boolean_t *inPlane )
2071 {
2072 CHECK( IORegistryEntry, registry_entry, entry );
2073
2074 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
2075
2076 return( kIOReturnSuccess );
2077 }
2078
2079
2080 /* Routine io_registry_entry_get_path */
2081 kern_return_t is_io_registry_entry_get_path(
2082 io_object_t registry_entry,
2083 io_name_t plane,
2084 io_string_t path )
2085 {
2086 int length;
2087 CHECK( IORegistryEntry, registry_entry, entry );
2088
2089 length = sizeof( io_string_t);
2090 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
2091 return( kIOReturnSuccess );
2092 else
2093 return( kIOReturnBadArgument );
2094 }
2095
2096
2097 /* Routine io_registry_entry_get_name */
2098 kern_return_t is_io_registry_entry_get_name(
2099 io_object_t registry_entry,
2100 io_name_t name )
2101 {
2102 CHECK( IORegistryEntry, registry_entry, entry );
2103
2104 strncpy( name, entry->getName(), sizeof( io_name_t));
2105
2106 return( kIOReturnSuccess );
2107 }
2108
2109 /* Routine io_registry_entry_get_name_in_plane */
2110 kern_return_t is_io_registry_entry_get_name_in_plane(
2111 io_object_t registry_entry,
2112 io_name_t planeName,
2113 io_name_t name )
2114 {
2115 const IORegistryPlane * plane;
2116 CHECK( IORegistryEntry, registry_entry, entry );
2117
2118 if( planeName[0])
2119 plane = IORegistryEntry::getPlane( planeName );
2120 else
2121 plane = 0;
2122
2123 strncpy( name, entry->getName( plane), sizeof( io_name_t));
2124
2125 return( kIOReturnSuccess );
2126 }
2127
2128 /* Routine io_registry_entry_get_location_in_plane */
2129 kern_return_t is_io_registry_entry_get_location_in_plane(
2130 io_object_t registry_entry,
2131 io_name_t planeName,
2132 io_name_t location )
2133 {
2134 const IORegistryPlane * plane;
2135 CHECK( IORegistryEntry, registry_entry, entry );
2136
2137 if( planeName[0])
2138 plane = IORegistryEntry::getPlane( planeName );
2139 else
2140 plane = 0;
2141
2142 const char * cstr = entry->getLocation( plane );
2143
2144 if( cstr) {
2145 strncpy( location, cstr, sizeof( io_name_t));
2146 return( kIOReturnSuccess );
2147 } else
2148 return( kIOReturnNotFound );
2149 }
2150
2151 /* Routine io_registry_entry_get_registry_entry_id */
2152 kern_return_t is_io_registry_entry_get_registry_entry_id(
2153 io_object_t registry_entry,
2154 uint64_t *entry_id )
2155 {
2156 CHECK( IORegistryEntry, registry_entry, entry );
2157
2158 *entry_id = entry->getRegistryEntryID();
2159
2160 return (kIOReturnSuccess);
2161 }
2162
2163 // Create a vm_map_copy_t or kalloc'ed data for memory
2164 // to be copied out. ipc will free after the copyout.
2165
2166 static kern_return_t copyoutkdata( const void * data, vm_size_t len,
2167 io_buf_ptr_t * buf )
2168 {
2169 kern_return_t err;
2170 vm_map_copy_t copy;
2171
2172 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
2173 false /* src_destroy */, &copy);
2174
2175 assert( err == KERN_SUCCESS );
2176 if( err == KERN_SUCCESS )
2177 *buf = (char *) copy;
2178
2179 return( err );
2180 }
2181
2182 /* Routine io_registry_entry_get_property */
2183 kern_return_t is_io_registry_entry_get_property_bytes(
2184 io_object_t registry_entry,
2185 io_name_t property_name,
2186 io_struct_inband_t buf,
2187 mach_msg_type_number_t *dataCnt )
2188 {
2189 OSObject * obj;
2190 OSData * data;
2191 OSString * str;
2192 OSBoolean * boo;
2193 OSNumber * off;
2194 UInt64 offsetBytes;
2195 unsigned int len = 0;
2196 const void * bytes = 0;
2197 IOReturn ret = kIOReturnSuccess;
2198
2199 CHECK( IORegistryEntry, registry_entry, entry );
2200
2201 obj = entry->copyProperty(property_name);
2202 if( !obj)
2203 return( kIOReturnNoResources );
2204
2205 // One day OSData will be a common container base class
2206 // until then...
2207 if( (data = OSDynamicCast( OSData, obj ))) {
2208 len = data->getLength();
2209 bytes = data->getBytesNoCopy();
2210
2211 } else if( (str = OSDynamicCast( OSString, obj ))) {
2212 len = str->getLength() + 1;
2213 bytes = str->getCStringNoCopy();
2214
2215 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
2216 len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
2217 bytes = boo->isTrue() ? "Yes" : "No";
2218
2219 } else if( (off = OSDynamicCast( OSNumber, obj ))) {
2220 offsetBytes = off->unsigned64BitValue();
2221 len = off->numberOfBytes();
2222 bytes = &offsetBytes;
2223 #ifdef __BIG_ENDIAN__
2224 bytes = (const void *)
2225 (((UInt32) bytes) + (sizeof( UInt64) - len));
2226 #endif
2227
2228 } else
2229 ret = kIOReturnBadArgument;
2230
2231 if( bytes) {
2232 if( *dataCnt < len)
2233 ret = kIOReturnIPCError;
2234 else {
2235 *dataCnt = len;
2236 bcopy( bytes, buf, len );
2237 }
2238 }
2239 obj->release();
2240
2241 return( ret );
2242 }
2243
2244
2245 /* Routine io_registry_entry_get_property */
2246 kern_return_t is_io_registry_entry_get_property(
2247 io_object_t registry_entry,
2248 io_name_t property_name,
2249 io_buf_ptr_t *properties,
2250 mach_msg_type_number_t *propertiesCnt )
2251 {
2252 kern_return_t err;
2253 vm_size_t len;
2254 OSObject * obj;
2255
2256 CHECK( IORegistryEntry, registry_entry, entry );
2257
2258 obj = entry->copyProperty(property_name);
2259 if( !obj)
2260 return( kIOReturnNotFound );
2261
2262 OSSerialize * s = OSSerialize::withCapacity(4096);
2263 if( !s) {
2264 obj->release();
2265 return( kIOReturnNoMemory );
2266 }
2267 s->clearText();
2268
2269 if( obj->serialize( s )) {
2270 len = s->getLength();
2271 *propertiesCnt = len;
2272 err = copyoutkdata( s->text(), len, properties );
2273
2274 } else
2275 err = kIOReturnUnsupported;
2276
2277 s->release();
2278 obj->release();
2279
2280 return( err );
2281 }
2282
2283 /* Routine io_registry_entry_get_property_recursively */
2284 kern_return_t is_io_registry_entry_get_property_recursively(
2285 io_object_t registry_entry,
2286 io_name_t plane,
2287 io_name_t property_name,
2288 uint32_t options,
2289 io_buf_ptr_t *properties,
2290 mach_msg_type_number_t *propertiesCnt )
2291 {
2292 kern_return_t err;
2293 vm_size_t len;
2294 OSObject * obj;
2295
2296 CHECK( IORegistryEntry, registry_entry, entry );
2297
2298 obj = entry->copyProperty( property_name,
2299 IORegistryEntry::getPlane( plane ), options);
2300 if( !obj)
2301 return( kIOReturnNotFound );
2302
2303 OSSerialize * s = OSSerialize::withCapacity(4096);
2304 if( !s) {
2305 obj->release();
2306 return( kIOReturnNoMemory );
2307 }
2308
2309 s->clearText();
2310
2311 if( obj->serialize( s )) {
2312 len = s->getLength();
2313 *propertiesCnt = len;
2314 err = copyoutkdata( s->text(), len, properties );
2315
2316 } else
2317 err = kIOReturnUnsupported;
2318
2319 s->release();
2320 obj->release();
2321
2322 return( err );
2323 }
2324
2325 /* Routine io_registry_entry_get_properties */
2326 kern_return_t is_io_registry_entry_get_properties(
2327 io_object_t registry_entry,
2328 io_buf_ptr_t *properties,
2329 mach_msg_type_number_t *propertiesCnt )
2330 {
2331 kern_return_t err;
2332 vm_size_t len;
2333
2334 CHECK( IORegistryEntry, registry_entry, entry );
2335
2336 OSSerialize * s = OSSerialize::withCapacity(4096);
2337 if( !s)
2338 return( kIOReturnNoMemory );
2339
2340 s->clearText();
2341
2342 if( entry->serializeProperties( s )) {
2343 len = s->getLength();
2344 *propertiesCnt = len;
2345 err = copyoutkdata( s->text(), len, properties );
2346
2347 } else
2348 err = kIOReturnUnsupported;
2349
2350 s->release();
2351
2352 return( err );
2353 }
2354
2355 /* Routine io_registry_entry_set_properties */
2356 kern_return_t is_io_registry_entry_set_properties
2357 (
2358 io_object_t registry_entry,
2359 io_buf_ptr_t properties,
2360 mach_msg_type_number_t propertiesCnt,
2361 kern_return_t * result)
2362 {
2363 OSObject * obj;
2364 kern_return_t err;
2365 IOReturn res;
2366 vm_offset_t data;
2367 vm_map_offset_t map_data;
2368
2369 CHECK( IORegistryEntry, registry_entry, entry );
2370
2371 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2372 data = CAST_DOWN(vm_offset_t, map_data);
2373
2374 if( KERN_SUCCESS == err) {
2375
2376 // must return success after vm_map_copyout() succeeds
2377 obj = OSUnserializeXML( (const char *) data );
2378 vm_deallocate( kernel_map, data, propertiesCnt );
2379
2380 if (!obj)
2381 res = kIOReturnBadArgument;
2382 #if CONFIG_MACF
2383 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
2384 registry_entry, obj))
2385 res = kIOReturnNotPermitted;
2386 #endif
2387 else
2388 res = entry->setProperties( obj );
2389 if (obj)
2390 obj->release();
2391 } else
2392 res = err;
2393
2394 *result = res;
2395 return( err );
2396 }
2397
2398 /* Routine io_registry_entry_get_child_iterator */
2399 kern_return_t is_io_registry_entry_get_child_iterator(
2400 io_object_t registry_entry,
2401 io_name_t plane,
2402 io_object_t *iterator )
2403 {
2404 CHECK( IORegistryEntry, registry_entry, entry );
2405
2406 *iterator = entry->getChildIterator(
2407 IORegistryEntry::getPlane( plane ));
2408
2409 return( kIOReturnSuccess );
2410 }
2411
2412 /* Routine io_registry_entry_get_parent_iterator */
2413 kern_return_t is_io_registry_entry_get_parent_iterator(
2414 io_object_t registry_entry,
2415 io_name_t plane,
2416 io_object_t *iterator)
2417 {
2418 CHECK( IORegistryEntry, registry_entry, entry );
2419
2420 *iterator = entry->getParentIterator(
2421 IORegistryEntry::getPlane( plane ));
2422
2423 return( kIOReturnSuccess );
2424 }
2425
2426 /* Routine io_service_get_busy_state */
2427 kern_return_t is_io_service_get_busy_state(
2428 io_object_t _service,
2429 uint32_t *busyState )
2430 {
2431 CHECK( IOService, _service, service );
2432
2433 *busyState = service->getBusyState();
2434
2435 return( kIOReturnSuccess );
2436 }
2437
2438 /* Routine io_service_get_state */
2439 kern_return_t is_io_service_get_state(
2440 io_object_t _service,
2441 uint64_t *state,
2442 uint32_t *busy_state,
2443 uint64_t *accumulated_busy_time )
2444 {
2445 CHECK( IOService, _service, service );
2446
2447 *state = service->getState();
2448 *busy_state = service->getBusyState();
2449 *accumulated_busy_time = service->getAccumulatedBusyTime();
2450
2451 return( kIOReturnSuccess );
2452 }
2453
2454 /* Routine io_service_wait_quiet */
2455 kern_return_t is_io_service_wait_quiet(
2456 io_object_t _service,
2457 mach_timespec_t wait_time )
2458 {
2459 uint64_t timeoutNS;
2460
2461 CHECK( IOService, _service, service );
2462
2463 timeoutNS = wait_time.tv_sec;
2464 timeoutNS *= kSecondScale;
2465 timeoutNS += wait_time.tv_nsec;
2466
2467 return( service->waitQuiet(timeoutNS) );
2468 }
2469
2470 /* Routine io_service_request_probe */
2471 kern_return_t is_io_service_request_probe(
2472 io_object_t _service,
2473 uint32_t options )
2474 {
2475 CHECK( IOService, _service, service );
2476
2477 return( service->requestProbe( options ));
2478 }
2479
2480 /* Routine io_service_open_ndr */
2481 kern_return_t is_io_service_open_extended(
2482 io_object_t _service,
2483 task_t owningTask,
2484 uint32_t connect_type,
2485 NDR_record_t ndr,
2486 io_buf_ptr_t properties,
2487 mach_msg_type_number_t propertiesCnt,
2488 kern_return_t * result,
2489 io_object_t *connection )
2490 {
2491 IOUserClient * client = 0;
2492 kern_return_t err = KERN_SUCCESS;
2493 IOReturn res = kIOReturnSuccess;
2494 OSDictionary * propertiesDict = 0;
2495 bool crossEndian;
2496 bool disallowAccess;
2497
2498 CHECK( IOService, _service, service );
2499
2500 do
2501 {
2502 if (properties)
2503 {
2504 OSObject * obj;
2505 vm_offset_t data;
2506 vm_map_offset_t map_data;
2507
2508 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2509 res = err;
2510 data = CAST_DOWN(vm_offset_t, map_data);
2511 if (KERN_SUCCESS == err)
2512 {
2513 // must return success after vm_map_copyout() succeeds
2514 obj = OSUnserializeXML( (const char *) data );
2515 vm_deallocate( kernel_map, data, propertiesCnt );
2516 propertiesDict = OSDynamicCast(OSDictionary, obj);
2517 if (!propertiesDict)
2518 {
2519 res = kIOReturnBadArgument;
2520 if (obj)
2521 obj->release();
2522 }
2523 }
2524 if (kIOReturnSuccess != res)
2525 break;
2526 }
2527
2528 crossEndian = (ndr.int_rep != NDR_record.int_rep);
2529 if (crossEndian)
2530 {
2531 if (!propertiesDict)
2532 propertiesDict = OSDictionary::withCapacity(4);
2533 OSData * data = OSData::withBytes(&ndr, sizeof(ndr));
2534 if (data)
2535 {
2536 if (propertiesDict)
2537 propertiesDict->setObject(kIOUserClientCrossEndianKey, data);
2538 data->release();
2539 }
2540 }
2541
2542 res = service->newUserClient( owningTask, (void *) owningTask,
2543 connect_type, propertiesDict, &client );
2544
2545 if (propertiesDict)
2546 propertiesDict->release();
2547
2548 if (res == kIOReturnSuccess)
2549 {
2550 assert( OSDynamicCast(IOUserClient, client) );
2551
2552 disallowAccess = (crossEndian
2553 && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
2554 && (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
2555 if (disallowAccess) res = kIOReturnUnsupported;
2556 #if CONFIG_MACF
2557 else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type))
2558 res = kIOReturnNotPermitted;
2559 #endif
2560 if (kIOReturnSuccess != res)
2561 {
2562 IOStatisticsClientCall();
2563 client->clientClose();
2564 client->release();
2565 client = 0;
2566 break;
2567 }
2568 client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
2569 OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
2570 if (creatorName)
2571 {
2572 client->setProperty(kIOUserClientCreatorKey, creatorName);
2573 creatorName->release();
2574 }
2575 }
2576 }
2577 while (false);
2578
2579 *connection = client;
2580 *result = res;
2581
2582 return (err);
2583 }
2584
2585 /* Routine io_service_close */
2586 kern_return_t is_io_service_close(
2587 io_object_t connection )
2588 {
2589 OSSet * mappings;
2590 if ((mappings = OSDynamicCast(OSSet, connection)))
2591 return( kIOReturnSuccess );
2592
2593 CHECK( IOUserClient, connection, client );
2594
2595 IOStatisticsClientCall();
2596 client->clientClose();
2597
2598 return( kIOReturnSuccess );
2599 }
2600
2601 /* Routine io_connect_get_service */
2602 kern_return_t is_io_connect_get_service(
2603 io_object_t connection,
2604 io_object_t *service )
2605 {
2606 IOService * theService;
2607
2608 CHECK( IOUserClient, connection, client );
2609
2610 theService = client->getService();
2611 if( theService)
2612 theService->retain();
2613
2614 *service = theService;
2615
2616 return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
2617 }
2618
2619 /* Routine io_connect_set_notification_port */
2620 kern_return_t is_io_connect_set_notification_port(
2621 io_object_t connection,
2622 uint32_t notification_type,
2623 mach_port_t port,
2624 uint32_t reference)
2625 {
2626 CHECK( IOUserClient, connection, client );
2627
2628 IOStatisticsClientCall();
2629 return( client->registerNotificationPort( port, notification_type,
2630 (io_user_reference_t) reference ));
2631 }
2632
2633 /* Routine io_connect_set_notification_port */
2634 kern_return_t is_io_connect_set_notification_port_64(
2635 io_object_t connection,
2636 uint32_t notification_type,
2637 mach_port_t port,
2638 io_user_reference_t reference)
2639 {
2640 CHECK( IOUserClient, connection, client );
2641
2642 IOStatisticsClientCall();
2643 return( client->registerNotificationPort( port, notification_type,
2644 reference ));
2645 }
2646
2647 /* Routine io_connect_map_memory_into_task */
2648 kern_return_t is_io_connect_map_memory_into_task
2649 (
2650 io_connect_t connection,
2651 uint32_t memory_type,
2652 task_t into_task,
2653 mach_vm_address_t *address,
2654 mach_vm_size_t *size,
2655 uint32_t flags
2656 )
2657 {
2658 IOReturn err;
2659 IOMemoryMap * map;
2660
2661 CHECK( IOUserClient, connection, client );
2662
2663 IOStatisticsClientCall();
2664 map = client->mapClientMemory64( memory_type, into_task, flags, *address );
2665
2666 if( map) {
2667 *address = map->getAddress();
2668 if( size)
2669 *size = map->getSize();
2670
2671 if( client->sharedInstance
2672 || (into_task != current_task())) {
2673 // push a name out to the task owning the map,
2674 // so we can clean up maps
2675 mach_port_name_t name __unused =
2676 IOMachPort::makeSendRightForTask(
2677 into_task, map, IKOT_IOKIT_OBJECT );
2678 assert( name );
2679
2680 } else {
2681 // keep it with the user client
2682 IOLockLock( gIOObjectPortLock);
2683 if( 0 == client->mappings)
2684 client->mappings = OSSet::withCapacity(2);
2685 if( client->mappings)
2686 client->mappings->setObject( map);
2687 IOLockUnlock( gIOObjectPortLock);
2688 map->release();
2689 }
2690 err = kIOReturnSuccess;
2691
2692 } else
2693 err = kIOReturnBadArgument;
2694
2695 return( err );
2696 }
2697
2698 /* Routine is_io_connect_map_memory */
2699 kern_return_t is_io_connect_map_memory(
2700 io_object_t connect,
2701 uint32_t type,
2702 task_t task,
2703 vm_address_t * mapAddr,
2704 vm_size_t * mapSize,
2705 uint32_t flags )
2706 {
2707 IOReturn err;
2708 mach_vm_address_t address;
2709 mach_vm_size_t size;
2710
2711 address = SCALAR64(*mapAddr);
2712 size = SCALAR64(*mapSize);
2713
2714 err = is_io_connect_map_memory_into_task(connect, type, task, &address, &size, flags);
2715
2716 *mapAddr = SCALAR32(address);
2717 *mapSize = SCALAR32(size);
2718
2719 return (err);
2720 }
2721
2722 } /* extern "C" */
2723
2724 IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
2725 {
2726 OSIterator * iter;
2727 IOMemoryMap * map = 0;
2728
2729 IOLockLock(gIOObjectPortLock);
2730
2731 iter = OSCollectionIterator::withCollection(mappings);
2732 if(iter)
2733 {
2734 while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject())))
2735 {
2736 if(mem == map->getMemoryDescriptor())
2737 {
2738 map->retain();
2739 mappings->removeObject(map);
2740 break;
2741 }
2742 }
2743 iter->release();
2744 }
2745
2746 IOLockUnlock(gIOObjectPortLock);
2747
2748 return (map);
2749 }
2750
2751 extern "C" {
2752
2753 /* Routine io_connect_unmap_memory_from_task */
2754 kern_return_t is_io_connect_unmap_memory_from_task
2755 (
2756 io_connect_t connection,
2757 uint32_t memory_type,
2758 task_t from_task,
2759 mach_vm_address_t address)
2760 {
2761 IOReturn err;
2762 IOOptionBits options = 0;
2763 IOMemoryDescriptor * memory;
2764 IOMemoryMap * map;
2765
2766 CHECK( IOUserClient, connection, client );
2767
2768 IOStatisticsClientCall();
2769 err = client->clientMemoryForType( (UInt32) memory_type, &options, &memory );
2770
2771 if( memory && (kIOReturnSuccess == err)) {
2772
2773 options = (options & ~kIOMapUserOptionsMask)
2774 | kIOMapAnywhere | kIOMapReference;
2775
2776 map = memory->createMappingInTask( from_task, address, options );
2777 memory->release();
2778 if( map)
2779 {
2780 IOLockLock( gIOObjectPortLock);
2781 if( client->mappings)
2782 client->mappings->removeObject( map);
2783 IOLockUnlock( gIOObjectPortLock);
2784
2785 mach_port_name_t name = 0;
2786 if (from_task != current_task())
2787 name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
2788 if (name)
2789 {
2790 map->userClientUnmap();
2791 err = iokit_mod_send_right( from_task, name, -2 );
2792 err = kIOReturnSuccess;
2793 }
2794 else
2795 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
2796 if (from_task == current_task())
2797 map->release();
2798 }
2799 else
2800 err = kIOReturnBadArgument;
2801 }
2802
2803 return( err );
2804 }
2805
2806 kern_return_t is_io_connect_unmap_memory(
2807 io_object_t connect,
2808 uint32_t type,
2809 task_t task,
2810 vm_address_t mapAddr )
2811 {
2812 IOReturn err;
2813 mach_vm_address_t address;
2814
2815 address = SCALAR64(mapAddr);
2816
2817 err = is_io_connect_unmap_memory_from_task(connect, type, task, mapAddr);
2818
2819 return (err);
2820 }
2821
2822
2823 /* Routine io_connect_add_client */
2824 kern_return_t is_io_connect_add_client(
2825 io_object_t connection,
2826 io_object_t connect_to)
2827 {
2828 CHECK( IOUserClient, connection, client );
2829 CHECK( IOUserClient, connect_to, to );
2830
2831 IOStatisticsClientCall();
2832 return( client->connectClient( to ) );
2833 }
2834
2835
2836 /* Routine io_connect_set_properties */
2837 kern_return_t is_io_connect_set_properties(
2838 io_object_t connection,
2839 io_buf_ptr_t properties,
2840 mach_msg_type_number_t propertiesCnt,
2841 kern_return_t * result)
2842 {
2843 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
2844 }
2845
2846 /* Routine io_user_client_method */
2847 kern_return_t is_io_connect_method_var_output
2848 (
2849 io_connect_t connection,
2850 uint32_t selector,
2851 io_scalar_inband64_t scalar_input,
2852 mach_msg_type_number_t scalar_inputCnt,
2853 io_struct_inband_t inband_input,
2854 mach_msg_type_number_t inband_inputCnt,
2855 mach_vm_address_t ool_input,
2856 mach_vm_size_t ool_input_size,
2857 io_struct_inband_t inband_output,
2858 mach_msg_type_number_t *inband_outputCnt,
2859 io_scalar_inband64_t scalar_output,
2860 mach_msg_type_number_t *scalar_outputCnt,
2861 io_buf_ptr_t *var_output,
2862 mach_msg_type_number_t *var_outputCnt
2863 )
2864 {
2865 CHECK( IOUserClient, connection, client );
2866
2867 IOExternalMethodArguments args;
2868 IOReturn ret;
2869 IOMemoryDescriptor * inputMD = 0;
2870 OSObject * structureVariableOutputData = 0;
2871
2872 bzero(&args.__reserved[0], sizeof(args.__reserved));
2873 args.version = kIOExternalMethodArgumentsCurrentVersion;
2874
2875 args.selector = selector;
2876
2877 args.asyncWakePort = MACH_PORT_NULL;
2878 args.asyncReference = 0;
2879 args.asyncReferenceCount = 0;
2880 args.structureVariableOutputData = &structureVariableOutputData;
2881
2882 args.scalarInput = scalar_input;
2883 args.scalarInputCount = scalar_inputCnt;
2884 args.structureInput = inband_input;
2885 args.structureInputSize = inband_inputCnt;
2886
2887 if (ool_input)
2888 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2889 kIODirectionOut, current_task());
2890
2891 args.structureInputDescriptor = inputMD;
2892
2893 args.scalarOutput = scalar_output;
2894 args.scalarOutputCount = *scalar_outputCnt;
2895 args.structureOutput = inband_output;
2896 args.structureOutputSize = *inband_outputCnt;
2897 args.structureOutputDescriptor = NULL;
2898 args.structureOutputDescriptorSize = 0;
2899
2900 IOStatisticsClientCall();
2901 ret = client->externalMethod( selector, &args );
2902
2903 *scalar_outputCnt = args.scalarOutputCount;
2904 *inband_outputCnt = args.structureOutputSize;
2905
2906 if (var_outputCnt && var_output && (kIOReturnSuccess == ret))
2907 {
2908 OSSerialize * serialize;
2909 OSData * data;
2910 vm_size_t len;
2911
2912 if ((serialize = OSDynamicCast(OSSerialize, structureVariableOutputData)))
2913 {
2914 len = serialize->getLength();
2915 *var_outputCnt = len;
2916 ret = copyoutkdata(serialize->text(), len, var_output);
2917 }
2918 else if ((data = OSDynamicCast(OSData, structureVariableOutputData)))
2919 {
2920 len = data->getLength();
2921 *var_outputCnt = len;
2922 ret = copyoutkdata(data->getBytesNoCopy(), len, var_output);
2923 }
2924 else
2925 {
2926 ret = kIOReturnUnderrun;
2927 }
2928 }
2929
2930 if (inputMD)
2931 inputMD->release();
2932 if (structureVariableOutputData)
2933 structureVariableOutputData->release();
2934
2935 return (ret);
2936 }
2937
2938 /* Routine io_user_client_method */
2939 kern_return_t is_io_connect_method
2940 (
2941 io_connect_t connection,
2942 uint32_t selector,
2943 io_scalar_inband64_t scalar_input,
2944 mach_msg_type_number_t scalar_inputCnt,
2945 io_struct_inband_t inband_input,
2946 mach_msg_type_number_t inband_inputCnt,
2947 mach_vm_address_t ool_input,
2948 mach_vm_size_t ool_input_size,
2949 io_struct_inband_t inband_output,
2950 mach_msg_type_number_t *inband_outputCnt,
2951 io_scalar_inband64_t scalar_output,
2952 mach_msg_type_number_t *scalar_outputCnt,
2953 mach_vm_address_t ool_output,
2954 mach_vm_size_t *ool_output_size
2955 )
2956 {
2957 CHECK( IOUserClient, connection, client );
2958
2959 IOExternalMethodArguments args;
2960 IOReturn ret;
2961 IOMemoryDescriptor * inputMD = 0;
2962 IOMemoryDescriptor * outputMD = 0;
2963
2964 bzero(&args.__reserved[0], sizeof(args.__reserved));
2965 args.version = kIOExternalMethodArgumentsCurrentVersion;
2966
2967 args.selector = selector;
2968
2969 args.asyncWakePort = MACH_PORT_NULL;
2970 args.asyncReference = 0;
2971 args.asyncReferenceCount = 0;
2972 args.structureVariableOutputData = 0;
2973
2974 args.scalarInput = scalar_input;
2975 args.scalarInputCount = scalar_inputCnt;
2976 args.structureInput = inband_input;
2977 args.structureInputSize = inband_inputCnt;
2978
2979 if (ool_input)
2980 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2981 kIODirectionOut, current_task());
2982
2983 args.structureInputDescriptor = inputMD;
2984
2985 args.scalarOutput = scalar_output;
2986 args.scalarOutputCount = *scalar_outputCnt;
2987 args.structureOutput = inband_output;
2988 args.structureOutputSize = *inband_outputCnt;
2989
2990 if (ool_output && ool_output_size)
2991 {
2992 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
2993 kIODirectionIn, current_task());
2994 }
2995
2996 args.structureOutputDescriptor = outputMD;
2997 args.structureOutputDescriptorSize = ool_output_size ? *ool_output_size : 0;
2998
2999 IOStatisticsClientCall();
3000 ret = client->externalMethod( selector, &args );
3001
3002 *scalar_outputCnt = args.scalarOutputCount;
3003 *inband_outputCnt = args.structureOutputSize;
3004 *ool_output_size = args.structureOutputDescriptorSize;
3005
3006 if (inputMD)
3007 inputMD->release();
3008 if (outputMD)
3009 outputMD->release();
3010
3011 return (ret);
3012 }
3013
3014 /* Routine io_async_user_client_method */
3015 kern_return_t is_io_connect_async_method
3016 (
3017 io_connect_t connection,
3018 mach_port_t wake_port,
3019 io_async_ref64_t reference,
3020 mach_msg_type_number_t referenceCnt,
3021 uint32_t selector,
3022 io_scalar_inband64_t scalar_input,
3023 mach_msg_type_number_t scalar_inputCnt,
3024 io_struct_inband_t inband_input,
3025 mach_msg_type_number_t inband_inputCnt,
3026 mach_vm_address_t ool_input,
3027 mach_vm_size_t ool_input_size,
3028 io_struct_inband_t inband_output,
3029 mach_msg_type_number_t *inband_outputCnt,
3030 io_scalar_inband64_t scalar_output,
3031 mach_msg_type_number_t *scalar_outputCnt,
3032 mach_vm_address_t ool_output,
3033 mach_vm_size_t * ool_output_size
3034 )
3035 {
3036 CHECK( IOUserClient, connection, client );
3037
3038 IOExternalMethodArguments args;
3039 IOReturn ret;
3040 IOMemoryDescriptor * inputMD = 0;
3041 IOMemoryDescriptor * outputMD = 0;
3042
3043 bzero(&args.__reserved[0], sizeof(args.__reserved));
3044 args.version = kIOExternalMethodArgumentsCurrentVersion;
3045
3046 reference[0] = (io_user_reference_t) wake_port;
3047 if (vm_map_is_64bit(get_task_map(current_task())))
3048 reference[0] |= kIOUCAsync64Flag;
3049
3050 args.selector = selector;
3051
3052 args.asyncWakePort = wake_port;
3053 args.asyncReference = reference;
3054 args.asyncReferenceCount = referenceCnt;
3055
3056 args.scalarInput = scalar_input;
3057 args.scalarInputCount = scalar_inputCnt;
3058 args.structureInput = inband_input;
3059 args.structureInputSize = inband_inputCnt;
3060
3061 if (ool_input)
3062 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
3063 kIODirectionOut, current_task());
3064
3065 args.structureInputDescriptor = inputMD;
3066
3067 args.scalarOutput = scalar_output;
3068 args.scalarOutputCount = *scalar_outputCnt;
3069 args.structureOutput = inband_output;
3070 args.structureOutputSize = *inband_outputCnt;
3071
3072 if (ool_output)
3073 {
3074 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
3075 kIODirectionIn, current_task());
3076 }
3077
3078 args.structureOutputDescriptor = outputMD;
3079 args.structureOutputDescriptorSize = *ool_output_size;
3080
3081 IOStatisticsClientCall();
3082 ret = client->externalMethod( selector, &args );
3083
3084 *inband_outputCnt = args.structureOutputSize;
3085 *ool_output_size = args.structureOutputDescriptorSize;
3086
3087 if (inputMD)
3088 inputMD->release();
3089 if (outputMD)
3090 outputMD->release();
3091
3092 return (ret);
3093 }
3094
3095 /* Routine io_connect_method_scalarI_scalarO */
3096 kern_return_t is_io_connect_method_scalarI_scalarO(
3097 io_object_t connect,
3098 uint32_t index,
3099 io_scalar_inband_t input,
3100 mach_msg_type_number_t inputCount,
3101 io_scalar_inband_t output,
3102 mach_msg_type_number_t * outputCount )
3103 {
3104 IOReturn err;
3105 uint32_t i;
3106 io_scalar_inband64_t _input;
3107 io_scalar_inband64_t _output;
3108
3109 mach_msg_type_number_t struct_outputCnt = 0;
3110 mach_vm_size_t ool_output_size = 0;
3111
3112 for (i = 0; i < inputCount; i++)
3113 _input[i] = SCALAR64(input[i]);
3114
3115 err = is_io_connect_method(connect, index,
3116 _input, inputCount,
3117 NULL, 0,
3118 0, 0,
3119 NULL, &struct_outputCnt,
3120 _output, outputCount,
3121 0, &ool_output_size);
3122
3123 for (i = 0; i < *outputCount; i++)
3124 output[i] = SCALAR32(_output[i]);
3125
3126 return (err);
3127 }
3128
3129 kern_return_t shim_io_connect_method_scalarI_scalarO(
3130 IOExternalMethod * method,
3131 IOService * object,
3132 const io_user_scalar_t * input,
3133 mach_msg_type_number_t inputCount,
3134 io_user_scalar_t * output,
3135 mach_msg_type_number_t * outputCount )
3136 {
3137 IOMethod func;
3138 io_scalar_inband_t _output;
3139 IOReturn err;
3140 err = kIOReturnBadArgument;
3141
3142 do {
3143
3144 if( inputCount != method->count0)
3145 {
3146 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3147 continue;
3148 }
3149 if( *outputCount != method->count1)
3150 {
3151 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3152 continue;
3153 }
3154
3155 func = method->func;
3156
3157 switch( inputCount) {
3158
3159 case 6:
3160 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3161 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
3162 break;
3163 case 5:
3164 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3165 ARG32(input[3]), ARG32(input[4]),
3166 &_output[0] );
3167 break;
3168 case 4:
3169 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3170 ARG32(input[3]),
3171 &_output[0], &_output[1] );
3172 break;
3173 case 3:
3174 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3175 &_output[0], &_output[1], &_output[2] );
3176 break;
3177 case 2:
3178 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3179 &_output[0], &_output[1], &_output[2],
3180 &_output[3] );
3181 break;
3182 case 1:
3183 err = (object->*func)( ARG32(input[0]),
3184 &_output[0], &_output[1], &_output[2],
3185 &_output[3], &_output[4] );
3186 break;
3187 case 0:
3188 err = (object->*func)( &_output[0], &_output[1], &_output[2],
3189 &_output[3], &_output[4], &_output[5] );
3190 break;
3191
3192 default:
3193 IOLog("%s: Bad method table\n", object->getName());
3194 }
3195 }
3196 while( false);
3197
3198 uint32_t i;
3199 for (i = 0; i < *outputCount; i++)
3200 output[i] = SCALAR32(_output[i]);
3201
3202 return( err);
3203 }
3204
3205 /* Routine io_async_method_scalarI_scalarO */
3206 kern_return_t is_io_async_method_scalarI_scalarO(
3207 io_object_t connect,
3208 mach_port_t wake_port,
3209 io_async_ref_t reference,
3210 mach_msg_type_number_t referenceCnt,
3211 uint32_t index,
3212 io_scalar_inband_t input,
3213 mach_msg_type_number_t inputCount,
3214 io_scalar_inband_t output,
3215 mach_msg_type_number_t * outputCount )
3216 {
3217 IOReturn err;
3218 uint32_t i;
3219 io_scalar_inband64_t _input;
3220 io_scalar_inband64_t _output;
3221 io_async_ref64_t _reference;
3222
3223 for (i = 0; i < referenceCnt; i++)
3224 _reference[i] = REF64(reference[i]);
3225
3226 mach_msg_type_number_t struct_outputCnt = 0;
3227 mach_vm_size_t ool_output_size = 0;
3228
3229 for (i = 0; i < inputCount; i++)
3230 _input[i] = SCALAR64(input[i]);
3231
3232 err = is_io_connect_async_method(connect,
3233 wake_port, _reference, referenceCnt,
3234 index,
3235 _input, inputCount,
3236 NULL, 0,
3237 0, 0,
3238 NULL, &struct_outputCnt,
3239 _output, outputCount,
3240 0, &ool_output_size);
3241
3242 for (i = 0; i < *outputCount; i++)
3243 output[i] = SCALAR32(_output[i]);
3244
3245 return (err);
3246 }
3247 /* Routine io_async_method_scalarI_structureO */
3248 kern_return_t is_io_async_method_scalarI_structureO(
3249 io_object_t connect,
3250 mach_port_t wake_port,
3251 io_async_ref_t reference,
3252 mach_msg_type_number_t referenceCnt,
3253 uint32_t index,
3254 io_scalar_inband_t input,
3255 mach_msg_type_number_t inputCount,
3256 io_struct_inband_t output,
3257 mach_msg_type_number_t * outputCount )
3258 {
3259 uint32_t i;
3260 io_scalar_inband64_t _input;
3261 io_async_ref64_t _reference;
3262
3263 for (i = 0; i < referenceCnt; i++)
3264 _reference[i] = REF64(reference[i]);
3265
3266 mach_msg_type_number_t scalar_outputCnt = 0;
3267 mach_vm_size_t ool_output_size = 0;
3268
3269 for (i = 0; i < inputCount; i++)
3270 _input[i] = SCALAR64(input[i]);
3271
3272 return (is_io_connect_async_method(connect,
3273 wake_port, _reference, referenceCnt,
3274 index,
3275 _input, inputCount,
3276 NULL, 0,
3277 0, 0,
3278 output, outputCount,
3279 NULL, &scalar_outputCnt,
3280 0, &ool_output_size));
3281 }
3282
3283 /* Routine io_async_method_scalarI_structureI */
3284 kern_return_t is_io_async_method_scalarI_structureI(
3285 io_connect_t connect,
3286 mach_port_t wake_port,
3287 io_async_ref_t reference,
3288 mach_msg_type_number_t referenceCnt,
3289 uint32_t index,
3290 io_scalar_inband_t input,
3291 mach_msg_type_number_t inputCount,
3292 io_struct_inband_t inputStruct,
3293 mach_msg_type_number_t inputStructCount )
3294 {
3295 uint32_t i;
3296 io_scalar_inband64_t _input;
3297 io_async_ref64_t _reference;
3298
3299 for (i = 0; i < referenceCnt; i++)
3300 _reference[i] = REF64(reference[i]);
3301
3302 mach_msg_type_number_t scalar_outputCnt = 0;
3303 mach_msg_type_number_t inband_outputCnt = 0;
3304 mach_vm_size_t ool_output_size = 0;
3305
3306 for (i = 0; i < inputCount; i++)
3307 _input[i] = SCALAR64(input[i]);
3308
3309 return (is_io_connect_async_method(connect,
3310 wake_port, _reference, referenceCnt,
3311 index,
3312 _input, inputCount,
3313 inputStruct, inputStructCount,
3314 0, 0,
3315 NULL, &inband_outputCnt,
3316 NULL, &scalar_outputCnt,
3317 0, &ool_output_size));
3318 }
3319
3320 /* Routine io_async_method_structureI_structureO */
3321 kern_return_t is_io_async_method_structureI_structureO(
3322 io_object_t connect,
3323 mach_port_t wake_port,
3324 io_async_ref_t reference,
3325 mach_msg_type_number_t referenceCnt,
3326 uint32_t index,
3327 io_struct_inband_t input,
3328 mach_msg_type_number_t inputCount,
3329 io_struct_inband_t output,
3330 mach_msg_type_number_t * outputCount )
3331 {
3332 uint32_t i;
3333 mach_msg_type_number_t scalar_outputCnt = 0;
3334 mach_vm_size_t ool_output_size = 0;
3335 io_async_ref64_t _reference;
3336
3337 for (i = 0; i < referenceCnt; i++)
3338 _reference[i] = REF64(reference[i]);
3339
3340 return (is_io_connect_async_method(connect,
3341 wake_port, _reference, referenceCnt,
3342 index,
3343 NULL, 0,
3344 input, inputCount,
3345 0, 0,
3346 output, outputCount,
3347 NULL, &scalar_outputCnt,
3348 0, &ool_output_size));
3349 }
3350
3351
3352 kern_return_t shim_io_async_method_scalarI_scalarO(
3353 IOExternalAsyncMethod * method,
3354 IOService * object,
3355 mach_port_t asyncWakePort,
3356 io_user_reference_t * asyncReference,
3357 uint32_t asyncReferenceCount,
3358 const io_user_scalar_t * input,
3359 mach_msg_type_number_t inputCount,
3360 io_user_scalar_t * output,
3361 mach_msg_type_number_t * outputCount )
3362 {
3363 IOAsyncMethod func;
3364 uint32_t i;
3365 io_scalar_inband_t _output;
3366 IOReturn err;
3367 io_async_ref_t reference;
3368
3369 for (i = 0; i < asyncReferenceCount; i++)
3370 reference[i] = REF32(asyncReference[i]);
3371
3372 err = kIOReturnBadArgument;
3373
3374 do {
3375
3376 if( inputCount != method->count0)
3377 {
3378 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3379 continue;
3380 }
3381 if( *outputCount != method->count1)
3382 {
3383 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3384 continue;
3385 }
3386
3387 func = method->func;
3388
3389 switch( inputCount) {
3390
3391 case 6:
3392 err = (object->*func)( reference,
3393 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3394 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
3395 break;
3396 case 5:
3397 err = (object->*func)( reference,
3398 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3399 ARG32(input[3]), ARG32(input[4]),
3400 &_output[0] );
3401 break;
3402 case 4:
3403 err = (object->*func)( reference,
3404 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3405 ARG32(input[3]),
3406 &_output[0], &_output[1] );
3407 break;
3408 case 3:
3409 err = (object->*func)( reference,
3410 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3411 &_output[0], &_output[1], &_output[2] );
3412 break;
3413 case 2:
3414 err = (object->*func)( reference,
3415 ARG32(input[0]), ARG32(input[1]),
3416 &_output[0], &_output[1], &_output[2],
3417 &_output[3] );
3418 break;
3419 case 1:
3420 err = (object->*func)( reference,
3421 ARG32(input[0]),
3422 &_output[0], &_output[1], &_output[2],
3423 &_output[3], &_output[4] );
3424 break;
3425 case 0:
3426 err = (object->*func)( reference,
3427 &_output[0], &_output[1], &_output[2],
3428 &_output[3], &_output[4], &_output[5] );
3429 break;
3430
3431 default:
3432 IOLog("%s: Bad method table\n", object->getName());
3433 }
3434 }
3435 while( false);
3436
3437 for (i = 0; i < *outputCount; i++)
3438 output[i] = SCALAR32(_output[i]);
3439
3440 return( err);
3441 }
3442
3443
3444 /* Routine io_connect_method_scalarI_structureO */
3445 kern_return_t is_io_connect_method_scalarI_structureO(
3446 io_object_t connect,
3447 uint32_t index,
3448 io_scalar_inband_t input,
3449 mach_msg_type_number_t inputCount,
3450 io_struct_inband_t output,
3451 mach_msg_type_number_t * outputCount )
3452 {
3453 uint32_t i;
3454 io_scalar_inband64_t _input;
3455
3456 mach_msg_type_number_t scalar_outputCnt = 0;
3457 mach_vm_size_t ool_output_size = 0;
3458
3459 for (i = 0; i < inputCount; i++)
3460 _input[i] = SCALAR64(input[i]);
3461
3462 return (is_io_connect_method(connect, index,
3463 _input, inputCount,
3464 NULL, 0,
3465 0, 0,
3466 output, outputCount,
3467 NULL, &scalar_outputCnt,
3468 0, &ool_output_size));
3469 }
3470
3471 kern_return_t shim_io_connect_method_scalarI_structureO(
3472
3473 IOExternalMethod * method,
3474 IOService * object,
3475 const io_user_scalar_t * input,
3476 mach_msg_type_number_t inputCount,
3477 io_struct_inband_t output,
3478 IOByteCount * outputCount )
3479 {
3480 IOMethod func;
3481 IOReturn err;
3482
3483 err = kIOReturnBadArgument;
3484
3485 do {
3486 if( inputCount != method->count0)
3487 {
3488 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3489 continue;
3490 }
3491 if( (kIOUCVariableStructureSize != method->count1)
3492 && (*outputCount != method->count1))
3493 {
3494 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3495 continue;
3496 }
3497
3498 func = method->func;
3499
3500 switch( inputCount) {
3501
3502 case 5:
3503 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3504 ARG32(input[3]), ARG32(input[4]),
3505 output );
3506 break;
3507 case 4:
3508 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3509 ARG32(input[3]),
3510 output, (void *)outputCount );
3511 break;
3512 case 3:
3513 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3514 output, (void *)outputCount, 0 );
3515 break;
3516 case 2:
3517 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3518 output, (void *)outputCount, 0, 0 );
3519 break;
3520 case 1:
3521 err = (object->*func)( ARG32(input[0]),
3522 output, (void *)outputCount, 0, 0, 0 );
3523 break;
3524 case 0:
3525 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 );
3526 break;
3527
3528 default:
3529 IOLog("%s: Bad method table\n", object->getName());
3530 }
3531 }
3532 while( false);
3533
3534 return( err);
3535 }
3536
3537
3538 kern_return_t shim_io_async_method_scalarI_structureO(
3539 IOExternalAsyncMethod * method,
3540 IOService * object,
3541 mach_port_t asyncWakePort,
3542 io_user_reference_t * asyncReference,
3543 uint32_t asyncReferenceCount,
3544 const io_user_scalar_t * input,
3545 mach_msg_type_number_t inputCount,
3546 io_struct_inband_t output,
3547 mach_msg_type_number_t * outputCount )
3548 {
3549 IOAsyncMethod func;
3550 uint32_t i;
3551 IOReturn err;
3552 io_async_ref_t reference;
3553
3554 for (i = 0; i < asyncReferenceCount; i++)
3555 reference[i] = REF32(asyncReference[i]);
3556
3557 err = kIOReturnBadArgument;
3558 do {
3559 if( inputCount != method->count0)
3560 {
3561 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3562 continue;
3563 }
3564 if( (kIOUCVariableStructureSize != method->count1)
3565 && (*outputCount != method->count1))
3566 {
3567 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3568 continue;
3569 }
3570
3571 func = method->func;
3572
3573 switch( inputCount) {
3574
3575 case 5:
3576 err = (object->*func)( reference,
3577 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3578 ARG32(input[3]), ARG32(input[4]),
3579 output );
3580 break;
3581 case 4:
3582 err = (object->*func)( reference,
3583 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3584 ARG32(input[3]),
3585 output, (void *)outputCount );
3586 break;
3587 case 3:
3588 err = (object->*func)( reference,
3589 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3590 output, (void *)outputCount, 0 );
3591 break;
3592 case 2:
3593 err = (object->*func)( reference,
3594 ARG32(input[0]), ARG32(input[1]),
3595 output, (void *)outputCount, 0, 0 );
3596 break;
3597 case 1:
3598 err = (object->*func)( reference,
3599 ARG32(input[0]),
3600 output, (void *)outputCount, 0, 0, 0 );
3601 break;
3602 case 0:
3603 err = (object->*func)( reference,
3604 output, (void *)outputCount, 0, 0, 0, 0 );
3605 break;
3606
3607 default:
3608 IOLog("%s: Bad method table\n", object->getName());
3609 }
3610 }
3611 while( false);
3612
3613 return( err);
3614 }
3615
3616 /* Routine io_connect_method_scalarI_structureI */
3617 kern_return_t is_io_connect_method_scalarI_structureI(
3618 io_connect_t connect,
3619 uint32_t index,
3620 io_scalar_inband_t input,
3621 mach_msg_type_number_t inputCount,
3622 io_struct_inband_t inputStruct,
3623 mach_msg_type_number_t inputStructCount )
3624 {
3625 uint32_t i;
3626 io_scalar_inband64_t _input;
3627
3628 mach_msg_type_number_t scalar_outputCnt = 0;
3629 mach_msg_type_number_t inband_outputCnt = 0;
3630 mach_vm_size_t ool_output_size = 0;
3631
3632 for (i = 0; i < inputCount; i++)
3633 _input[i] = SCALAR64(input[i]);
3634
3635 return (is_io_connect_method(connect, index,
3636 _input, inputCount,
3637 inputStruct, inputStructCount,
3638 0, 0,
3639 NULL, &inband_outputCnt,
3640 NULL, &scalar_outputCnt,
3641 0, &ool_output_size));
3642 }
3643
3644 kern_return_t shim_io_connect_method_scalarI_structureI(
3645 IOExternalMethod * method,
3646 IOService * object,
3647 const io_user_scalar_t * input,
3648 mach_msg_type_number_t inputCount,
3649 io_struct_inband_t inputStruct,
3650 mach_msg_type_number_t inputStructCount )
3651 {
3652 IOMethod func;
3653 IOReturn err = kIOReturnBadArgument;
3654
3655 do
3656 {
3657 if( (kIOUCVariableStructureSize != method->count0)
3658 && (inputCount != method->count0))
3659 {
3660 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3661 continue;
3662 }
3663 if( (kIOUCVariableStructureSize != method->count1)
3664 && (inputStructCount != method->count1))
3665 {
3666 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3667 continue;
3668 }
3669
3670 func = method->func;
3671
3672 switch( inputCount) {
3673
3674 case 5:
3675 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3676 ARG32(input[3]), ARG32(input[4]),
3677 inputStruct );
3678 break;
3679 case 4:
3680 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *) input[2],
3681 ARG32(input[3]),
3682 inputStruct, (void *)inputStructCount );
3683 break;
3684 case 3:
3685 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3686 inputStruct, (void *)inputStructCount,
3687 0 );
3688 break;
3689 case 2:
3690 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3691 inputStruct, (void *)inputStructCount,
3692 0, 0 );
3693 break;
3694 case 1:
3695 err = (object->*func)( ARG32(input[0]),
3696 inputStruct, (void *)inputStructCount,
3697 0, 0, 0 );
3698 break;
3699 case 0:
3700 err = (object->*func)( inputStruct, (void *)inputStructCount,
3701 0, 0, 0, 0 );
3702 break;
3703
3704 default:
3705 IOLog("%s: Bad method table\n", object->getName());
3706 }
3707 }
3708 while (false);
3709
3710 return( err);
3711 }
3712
3713 kern_return_t shim_io_async_method_scalarI_structureI(
3714 IOExternalAsyncMethod * method,
3715 IOService * object,
3716 mach_port_t asyncWakePort,
3717 io_user_reference_t * asyncReference,
3718 uint32_t asyncReferenceCount,
3719 const io_user_scalar_t * input,
3720 mach_msg_type_number_t inputCount,
3721 io_struct_inband_t inputStruct,
3722 mach_msg_type_number_t inputStructCount )
3723 {
3724 IOAsyncMethod func;
3725 uint32_t i;
3726 IOReturn err = kIOReturnBadArgument;
3727 io_async_ref_t reference;
3728
3729 for (i = 0; i < asyncReferenceCount; i++)
3730 reference[i] = REF32(asyncReference[i]);
3731
3732 do
3733 {
3734 if( (kIOUCVariableStructureSize != method->count0)
3735 && (inputCount != method->count0))
3736 {
3737 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3738 continue;
3739 }
3740 if( (kIOUCVariableStructureSize != method->count1)
3741 && (inputStructCount != method->count1))
3742 {
3743 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3744 continue;
3745 }
3746
3747 func = method->func;
3748
3749 switch( inputCount) {
3750
3751 case 5:
3752 err = (object->*func)( reference,
3753 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3754 ARG32(input[3]), ARG32(input[4]),
3755 inputStruct );
3756 break;
3757 case 4:
3758 err = (object->*func)( reference,
3759 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3760 ARG32(input[3]),
3761 inputStruct, (void *)inputStructCount );
3762 break;
3763 case 3:
3764 err = (object->*func)( reference,
3765 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3766 inputStruct, (void *)inputStructCount,
3767 0 );
3768 break;
3769 case 2:
3770 err = (object->*func)( reference,
3771 ARG32(input[0]), ARG32(input[1]),
3772 inputStruct, (void *)inputStructCount,
3773 0, 0 );
3774 break;
3775 case 1:
3776 err = (object->*func)( reference,
3777 ARG32(input[0]),
3778 inputStruct, (void *)inputStructCount,
3779 0, 0, 0 );
3780 break;
3781 case 0:
3782 err = (object->*func)( reference,
3783 inputStruct, (void *)inputStructCount,
3784 0, 0, 0, 0 );
3785 break;
3786
3787 default:
3788 IOLog("%s: Bad method table\n", object->getName());
3789 }
3790 }
3791 while (false);
3792
3793 return( err);
3794 }
3795
3796 /* Routine io_connect_method_structureI_structureO */
3797 kern_return_t is_io_connect_method_structureI_structureO(
3798 io_object_t connect,
3799 uint32_t index,
3800 io_struct_inband_t input,
3801 mach_msg_type_number_t inputCount,
3802 io_struct_inband_t output,
3803 mach_msg_type_number_t * outputCount )
3804 {
3805 mach_msg_type_number_t scalar_outputCnt = 0;
3806 mach_vm_size_t ool_output_size = 0;
3807
3808 return (is_io_connect_method(connect, index,
3809 NULL, 0,
3810 input, inputCount,
3811 0, 0,
3812 output, outputCount,
3813 NULL, &scalar_outputCnt,
3814 0, &ool_output_size));
3815 }
3816
3817 kern_return_t shim_io_connect_method_structureI_structureO(
3818 IOExternalMethod * method,
3819 IOService * object,
3820 io_struct_inband_t input,
3821 mach_msg_type_number_t inputCount,
3822 io_struct_inband_t output,
3823 IOByteCount * outputCount )
3824 {
3825 IOMethod func;
3826 IOReturn err = kIOReturnBadArgument;
3827
3828 do
3829 {
3830 if( (kIOUCVariableStructureSize != method->count0)
3831 && (inputCount != method->count0))
3832 {
3833 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3834 continue;
3835 }
3836 if( (kIOUCVariableStructureSize != method->count1)
3837 && (*outputCount != method->count1))
3838 {
3839 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3840 continue;
3841 }
3842
3843 func = method->func;
3844
3845 if( method->count1) {
3846 if( method->count0) {
3847 err = (object->*func)( input, output,
3848 (void *)inputCount, outputCount, 0, 0 );
3849 } else {
3850 err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
3851 }
3852 } else {
3853 err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
3854 }
3855 }
3856 while( false);
3857
3858
3859 return( err);
3860 }
3861
3862 kern_return_t shim_io_async_method_structureI_structureO(
3863 IOExternalAsyncMethod * method,
3864 IOService * object,
3865 mach_port_t asyncWakePort,
3866 io_user_reference_t * asyncReference,
3867 uint32_t asyncReferenceCount,
3868 io_struct_inband_t input,
3869 mach_msg_type_number_t inputCount,
3870 io_struct_inband_t output,
3871 mach_msg_type_number_t * outputCount )
3872 {
3873 IOAsyncMethod func;
3874 uint32_t i;
3875 IOReturn err;
3876 io_async_ref_t reference;
3877
3878 for (i = 0; i < asyncReferenceCount; i++)
3879 reference[i] = REF32(asyncReference[i]);
3880
3881 err = kIOReturnBadArgument;
3882 do
3883 {
3884 if( (kIOUCVariableStructureSize != method->count0)
3885 && (inputCount != method->count0))
3886 {
3887 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3888 continue;
3889 }
3890 if( (kIOUCVariableStructureSize != method->count1)
3891 && (*outputCount != method->count1))
3892 {
3893 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3894 continue;
3895 }
3896
3897 func = method->func;
3898
3899 if( method->count1) {
3900 if( method->count0) {
3901 err = (object->*func)( reference,
3902 input, output,
3903 (void *)inputCount, outputCount, 0, 0 );
3904 } else {
3905 err = (object->*func)( reference,
3906 output, outputCount, 0, 0, 0, 0 );
3907 }
3908 } else {
3909 err = (object->*func)( reference,
3910 input, (void *)inputCount, 0, 0, 0, 0 );
3911 }
3912 }
3913 while( false);
3914
3915 return( err);
3916 }
3917
3918 /* Routine io_catalog_send_data */
3919 kern_return_t is_io_catalog_send_data(
3920 mach_port_t master_port,
3921 uint32_t flag,
3922 io_buf_ptr_t inData,
3923 mach_msg_type_number_t inDataCount,
3924 kern_return_t * result)
3925 {
3926 OSObject * obj = 0;
3927 vm_offset_t data;
3928 kern_return_t kr = kIOReturnError;
3929
3930 //printf("io_catalog_send_data called. flag: %d\n", flag);
3931
3932 if( master_port != master_device_port)
3933 return kIOReturnNotPrivileged;
3934
3935 if( (flag != kIOCatalogRemoveKernelLinker &&
3936 flag != kIOCatalogKextdActive &&
3937 flag != kIOCatalogKextdFinishedLaunching) &&
3938 ( !inData || !inDataCount) )
3939 {
3940 return kIOReturnBadArgument;
3941 }
3942
3943 if (inData) {
3944 vm_map_offset_t map_data;
3945
3946 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
3947 data = CAST_DOWN(vm_offset_t, map_data);
3948
3949 if( kr != KERN_SUCCESS)
3950 return kr;
3951
3952 // must return success after vm_map_copyout() succeeds
3953
3954 if( inDataCount ) {
3955 obj = (OSObject *)OSUnserializeXML((const char *)data);
3956 vm_deallocate( kernel_map, data, inDataCount );
3957 if( !obj) {
3958 *result = kIOReturnNoMemory;
3959 return( KERN_SUCCESS);
3960 }
3961 }
3962 }
3963
3964 switch ( flag ) {
3965 case kIOCatalogResetDrivers:
3966 case kIOCatalogResetDriversNoMatch: {
3967 OSArray * array;
3968
3969 array = OSDynamicCast(OSArray, obj);
3970 if (array) {
3971 if ( !gIOCatalogue->resetAndAddDrivers(array,
3972 flag == kIOCatalogResetDrivers) ) {
3973
3974 kr = kIOReturnError;
3975 }
3976 } else {
3977 kr = kIOReturnBadArgument;
3978 }
3979 }
3980 break;
3981
3982 case kIOCatalogAddDrivers:
3983 case kIOCatalogAddDriversNoMatch: {
3984 OSArray * array;
3985
3986 array = OSDynamicCast(OSArray, obj);
3987 if ( array ) {
3988 if ( !gIOCatalogue->addDrivers( array ,
3989 flag == kIOCatalogAddDrivers) ) {
3990 kr = kIOReturnError;
3991 }
3992 }
3993 else {
3994 kr = kIOReturnBadArgument;
3995 }
3996 }
3997 break;
3998
3999 case kIOCatalogRemoveDrivers:
4000 case kIOCatalogRemoveDriversNoMatch: {
4001 OSDictionary * dict;
4002
4003 dict = OSDynamicCast(OSDictionary, obj);
4004 if ( dict ) {
4005 if ( !gIOCatalogue->removeDrivers( dict,
4006 flag == kIOCatalogRemoveDrivers ) ) {
4007 kr = kIOReturnError;
4008 }
4009 }
4010 else {
4011 kr = kIOReturnBadArgument;
4012 }
4013 }
4014 break;
4015
4016 case kIOCatalogStartMatching: {
4017 OSDictionary * dict;
4018
4019 dict = OSDynamicCast(OSDictionary, obj);
4020 if ( dict ) {
4021 if ( !gIOCatalogue->startMatching( dict ) ) {
4022 kr = kIOReturnError;
4023 }
4024 }
4025 else {
4026 kr = kIOReturnBadArgument;
4027 }
4028 }
4029 break;
4030
4031 case kIOCatalogRemoveKernelLinker:
4032 kr = KERN_NOT_SUPPORTED;
4033 break;
4034
4035 case kIOCatalogKextdActive:
4036 #if !NO_KEXTD
4037 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
4038 OSKext::setKextdActive();
4039
4040 /* Dump all nonloaded startup extensions; kextd will now send them
4041 * down on request.
4042 */
4043 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4044 #endif
4045 kr = kIOReturnSuccess;
4046 break;
4047
4048 case kIOCatalogKextdFinishedLaunching: {
4049 #if !NO_KEXTD
4050 static bool clearedBusy = false;
4051
4052 if (!clearedBusy) {
4053 IOService * serviceRoot = IOService::getServiceRoot();
4054 if (serviceRoot) {
4055 IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
4056 serviceRoot->adjustBusy(-1);
4057 clearedBusy = true;
4058 }
4059 }
4060 #endif
4061 kr = kIOReturnSuccess;
4062 }
4063 break;
4064
4065 default:
4066 kr = kIOReturnBadArgument;
4067 break;
4068 }
4069
4070 if (obj) obj->release();
4071
4072 *result = kr;
4073 return( KERN_SUCCESS);
4074 }
4075
4076 /* Routine io_catalog_terminate */
4077 kern_return_t is_io_catalog_terminate(
4078 mach_port_t master_port,
4079 uint32_t flag,
4080 io_name_t name )
4081 {
4082 kern_return_t kr;
4083
4084 if( master_port != master_device_port )
4085 return kIOReturnNotPrivileged;
4086
4087 kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
4088 kIOClientPrivilegeAdministrator );
4089 if( kIOReturnSuccess != kr)
4090 return( kr );
4091
4092 switch ( flag ) {
4093 #if !defined(SECURE_KERNEL)
4094 case kIOCatalogServiceTerminate:
4095 OSIterator * iter;
4096 IOService * service;
4097
4098 iter = IORegistryIterator::iterateOver(gIOServicePlane,
4099 kIORegistryIterateRecursively);
4100 if ( !iter )
4101 return kIOReturnNoMemory;
4102
4103 do {
4104 iter->reset();
4105 while( (service = (IOService *)iter->getNextObject()) ) {
4106 if( service->metaCast(name)) {
4107 if ( !service->terminate( kIOServiceRequired
4108 | kIOServiceSynchronous) ) {
4109 kr = kIOReturnUnsupported;
4110 break;
4111 }
4112 }
4113 }
4114 } while( !service && !iter->isValid());
4115 iter->release();
4116 break;
4117
4118 case kIOCatalogModuleUnload:
4119 case kIOCatalogModuleTerminate:
4120 kr = gIOCatalogue->terminateDriversForModule(name,
4121 flag == kIOCatalogModuleUnload);
4122 break;
4123 #endif
4124
4125 default:
4126 kr = kIOReturnBadArgument;
4127 break;
4128 }
4129
4130 return( kr );
4131 }
4132
4133 /* Routine io_catalog_get_data */
4134 kern_return_t is_io_catalog_get_data(
4135 mach_port_t master_port,
4136 uint32_t flag,
4137 io_buf_ptr_t *outData,
4138 mach_msg_type_number_t *outDataCount)
4139 {
4140 kern_return_t kr = kIOReturnSuccess;
4141 OSSerialize * s;
4142
4143 if( master_port != master_device_port)
4144 return kIOReturnNotPrivileged;
4145
4146 //printf("io_catalog_get_data called. flag: %d\n", flag);
4147
4148 s = OSSerialize::withCapacity(4096);
4149 if ( !s )
4150 return kIOReturnNoMemory;
4151
4152 s->clearText();
4153
4154 kr = gIOCatalogue->serializeData(flag, s);
4155
4156 if ( kr == kIOReturnSuccess ) {
4157 vm_offset_t data;
4158 vm_map_copy_t copy;
4159 vm_size_t size;
4160
4161 size = s->getLength();
4162 kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
4163 if ( kr == kIOReturnSuccess ) {
4164 bcopy(s->text(), (void *)data, size);
4165 kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
4166 (vm_map_size_t)size, true, &copy);
4167 *outData = (char *)copy;
4168 *outDataCount = size;
4169 }
4170 }
4171
4172 s->release();
4173
4174 return kr;
4175 }
4176
4177 /* Routine io_catalog_get_gen_count */
4178 kern_return_t is_io_catalog_get_gen_count(
4179 mach_port_t master_port,
4180 uint32_t *genCount)
4181 {
4182 if( master_port != master_device_port)
4183 return kIOReturnNotPrivileged;
4184
4185 //printf("io_catalog_get_gen_count called.\n");
4186
4187 if ( !genCount )
4188 return kIOReturnBadArgument;
4189
4190 *genCount = gIOCatalogue->getGenerationCount();
4191
4192 return kIOReturnSuccess;
4193 }
4194
4195 /* Routine io_catalog_module_loaded.
4196 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4197 */
4198 kern_return_t is_io_catalog_module_loaded(
4199 mach_port_t master_port,
4200 io_name_t name)
4201 {
4202 if( master_port != master_device_port)
4203 return kIOReturnNotPrivileged;
4204
4205 //printf("io_catalog_module_loaded called. name %s\n", name);
4206
4207 if ( !name )
4208 return kIOReturnBadArgument;
4209
4210 gIOCatalogue->moduleHasLoaded(name);
4211
4212 return kIOReturnSuccess;
4213 }
4214
4215 kern_return_t is_io_catalog_reset(
4216 mach_port_t master_port,
4217 uint32_t flag)
4218 {
4219 if( master_port != master_device_port)
4220 return kIOReturnNotPrivileged;
4221
4222 switch ( flag ) {
4223 case kIOCatalogResetDefault:
4224 gIOCatalogue->reset();
4225 break;
4226
4227 default:
4228 return kIOReturnBadArgument;
4229 }
4230
4231 return kIOReturnSuccess;
4232 }
4233
4234 kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
4235 {
4236 kern_return_t result = kIOReturnBadArgument;
4237 IOUserClient *userClient;
4238
4239 if ((userClient = OSDynamicCast(IOUserClient,
4240 iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
4241 IOExternalTrap *trap;
4242 IOService *target = NULL;
4243
4244 trap = userClient->getTargetAndTrapForIndex(&target, args->index);
4245
4246 if (trap && target) {
4247 IOTrap func;
4248
4249 func = trap->func;
4250
4251 if (func) {
4252 result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
4253 }
4254 }
4255
4256 userClient->release();
4257 }
4258
4259 return result;
4260 }
4261
4262 } /* extern "C" */
4263
4264 IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
4265 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
4266 {
4267 IOReturn err;
4268 IOService * object;
4269 IOByteCount structureOutputSize;
4270
4271 if (dispatch)
4272 {
4273 uint32_t count;
4274 count = dispatch->checkScalarInputCount;
4275 if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount))
4276 {
4277 return (kIOReturnBadArgument);
4278 }
4279
4280 count = dispatch->checkStructureInputSize;
4281 if ((kIOUCVariableStructureSize != count)
4282 && (count != ((args->structureInputDescriptor)
4283 ? args->structureInputDescriptor->getLength() : args->structureInputSize)))
4284 {
4285 return (kIOReturnBadArgument);
4286 }
4287
4288 count = dispatch->checkScalarOutputCount;
4289 if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount))
4290 {
4291 return (kIOReturnBadArgument);
4292 }
4293
4294 count = dispatch->checkStructureOutputSize;
4295 if ((kIOUCVariableStructureSize != count)
4296 && (count != ((args->structureOutputDescriptor)
4297 ? args->structureOutputDescriptor->getLength() : args->structureOutputSize)))
4298 {
4299 return (kIOReturnBadArgument);
4300 }
4301
4302 if (dispatch->function)
4303 err = (*dispatch->function)(target, reference, args);
4304 else
4305 err = kIOReturnNoCompletion; /* implementator can dispatch */
4306
4307 return (err);
4308 }
4309
4310
4311 // pre-Leopard API's don't do ool structs
4312 if (args->structureInputDescriptor || args->structureOutputDescriptor)
4313 {
4314 err = kIOReturnIPCError;
4315 return (err);
4316 }
4317
4318 structureOutputSize = args->structureOutputSize;
4319
4320 if (args->asyncWakePort)
4321 {
4322 IOExternalAsyncMethod * method;
4323
4324 if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) )
4325 return (kIOReturnUnsupported);
4326
4327 if (kIOUCForegroundOnly & method->flags)
4328 {
4329 /* is graphics access denied for current task? */
4330 if (proc_get_task_selfgpuacc_deny() != 0)
4331 return (kIOReturnNotPermitted);
4332 }
4333
4334 switch (method->flags & kIOUCTypeMask)
4335 {
4336 case kIOUCScalarIStructI:
4337 err = shim_io_async_method_scalarI_structureI( method, object,
4338 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4339 args->scalarInput, args->scalarInputCount,
4340 (char *)args->structureInput, args->structureInputSize );
4341 break;
4342
4343 case kIOUCScalarIScalarO:
4344 err = shim_io_async_method_scalarI_scalarO( method, object,
4345 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4346 args->scalarInput, args->scalarInputCount,
4347 args->scalarOutput, &args->scalarOutputCount );
4348 break;
4349
4350 case kIOUCScalarIStructO:
4351 err = shim_io_async_method_scalarI_structureO( method, object,
4352 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4353 args->scalarInput, args->scalarInputCount,
4354 (char *) args->structureOutput, &args->structureOutputSize );
4355 break;
4356
4357
4358 case kIOUCStructIStructO:
4359 err = shim_io_async_method_structureI_structureO( method, object,
4360 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4361 (char *)args->structureInput, args->structureInputSize,
4362 (char *) args->structureOutput, &args->structureOutputSize );
4363 break;
4364
4365 default:
4366 err = kIOReturnBadArgument;
4367 break;
4368 }
4369 }
4370 else
4371 {
4372 IOExternalMethod * method;
4373
4374 if( !(method = getTargetAndMethodForIndex(&object, selector)) )
4375 return (kIOReturnUnsupported);
4376
4377 if (kIOUCForegroundOnly & method->flags)
4378 {
4379 /* is graphics access denied for current task? */
4380 if (proc_get_task_selfgpuacc_deny() != 0)
4381 return (kIOReturnNotPermitted);
4382
4383 }
4384
4385 switch (method->flags & kIOUCTypeMask)
4386 {
4387 case kIOUCScalarIStructI:
4388 err = shim_io_connect_method_scalarI_structureI( method, object,
4389 args->scalarInput, args->scalarInputCount,
4390 (char *) args->structureInput, args->structureInputSize );
4391 break;
4392
4393 case kIOUCScalarIScalarO:
4394 err = shim_io_connect_method_scalarI_scalarO( method, object,
4395 args->scalarInput, args->scalarInputCount,
4396 args->scalarOutput, &args->scalarOutputCount );
4397 break;
4398
4399 case kIOUCScalarIStructO:
4400 err = shim_io_connect_method_scalarI_structureO( method, object,
4401 args->scalarInput, args->scalarInputCount,
4402 (char *) args->structureOutput, &structureOutputSize );
4403 break;
4404
4405
4406 case kIOUCStructIStructO:
4407 err = shim_io_connect_method_structureI_structureO( method, object,
4408 (char *) args->structureInput, args->structureInputSize,
4409 (char *) args->structureOutput, &structureOutputSize );
4410 break;
4411
4412 default:
4413 err = kIOReturnBadArgument;
4414 break;
4415 }
4416 }
4417
4418 args->structureOutputSize = structureOutputSize;
4419
4420 return (err);
4421 }
4422
4423
4424 #if __LP64__
4425 OSMetaClassDefineReservedUnused(IOUserClient, 0);
4426 OSMetaClassDefineReservedUnused(IOUserClient, 1);
4427 #else
4428 OSMetaClassDefineReservedUsed(IOUserClient, 0);
4429 OSMetaClassDefineReservedUsed(IOUserClient, 1);
4430 #endif
4431 OSMetaClassDefineReservedUnused(IOUserClient, 2);
4432 OSMetaClassDefineReservedUnused(IOUserClient, 3);
4433 OSMetaClassDefineReservedUnused(IOUserClient, 4);
4434 OSMetaClassDefineReservedUnused(IOUserClient, 5);
4435 OSMetaClassDefineReservedUnused(IOUserClient, 6);
4436 OSMetaClassDefineReservedUnused(IOUserClient, 7);
4437 OSMetaClassDefineReservedUnused(IOUserClient, 8);
4438 OSMetaClassDefineReservedUnused(IOUserClient, 9);
4439 OSMetaClassDefineReservedUnused(IOUserClient, 10);
4440 OSMetaClassDefineReservedUnused(IOUserClient, 11);
4441 OSMetaClassDefineReservedUnused(IOUserClient, 12);
4442 OSMetaClassDefineReservedUnused(IOUserClient, 13);
4443 OSMetaClassDefineReservedUnused(IOUserClient, 14);
4444 OSMetaClassDefineReservedUnused(IOUserClient, 15);
4445