]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOUserClient.cpp
xnu-792.17.14.tar.gz
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
1 /*
2 * Copyright (c) 1998-2004 Apple Computer, 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 <IOKit/IOKitServer.h>
31 #include <IOKit/IOKitKeysPrivate.h>
32 #include <IOKit/IOUserClient.h>
33 #include <IOKit/IOService.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/IOLib.h>
39
40 #include <IOKit/assert.h>
41
42 #include "IOServicePrivate.h"
43
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45
46 // definitions we should get from osfmk
47
48 //typedef struct ipc_port * ipc_port_t;
49 typedef natural_t ipc_kobject_type_t;
50
51 #define IKOT_IOKIT_SPARE 27
52 #define IKOT_IOKIT_CONNECT 29
53 #define IKOT_IOKIT_OBJECT 30
54
55 extern "C" {
56
57 extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
58 ipc_kobject_type_t type );
59
60 extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
61
62 extern mach_port_name_t iokit_make_send_right( task_t task,
63 io_object_t obj, ipc_kobject_type_t type );
64
65 extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta );
66
67 extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
68
69 extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
70
71 extern ipc_port_t master_device_port;
72
73 extern void iokit_retain_port( ipc_port_t port );
74 extern void iokit_release_port( ipc_port_t port );
75
76 extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type );
77
78 #include <mach/mach_traps.h>
79 #include <vm/vm_map.h>
80
81 } /* extern "C" */
82
83
84 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85
86 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
87
88 class IOMachPort : public OSObject
89 {
90 OSDeclareDefaultStructors(IOMachPort)
91 public:
92 OSObject * object;
93 ipc_port_t port;
94 UInt32 mscount;
95 UInt8 holdDestroy;
96
97 static IOMachPort * portForObject( OSObject * obj,
98 ipc_kobject_type_t type );
99 static bool noMoreSendersForObject( OSObject * obj,
100 ipc_kobject_type_t type, mach_port_mscount_t * mscount );
101 static void releasePortForObject( OSObject * obj,
102 ipc_kobject_type_t type );
103 static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type );
104
105 static OSDictionary * dictForType( ipc_kobject_type_t type );
106
107 static mach_port_name_t makeSendRightForTask( task_t task,
108 io_object_t obj, ipc_kobject_type_t type );
109
110 virtual void free();
111 };
112
113 #define super OSObject
114 OSDefineMetaClassAndStructors(IOMachPort, OSObject)
115
116 static IOLock * gIOObjectPortLock;
117
118 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
119
120 // not in dictForType() for debugging ease
121 static OSDictionary * gIOObjectPorts;
122 static OSDictionary * gIOConnectPorts;
123
124 OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
125 {
126 OSDictionary ** dict;
127
128 if( IKOT_IOKIT_OBJECT == type )
129 dict = &gIOObjectPorts;
130 else if( IKOT_IOKIT_CONNECT == type )
131 dict = &gIOConnectPorts;
132 else
133 return( 0 );
134
135 if( 0 == *dict)
136 *dict = OSDictionary::withCapacity( 1 );
137
138 return( *dict );
139 }
140
141 IOMachPort * IOMachPort::portForObject ( OSObject * obj,
142 ipc_kobject_type_t type )
143 {
144 IOMachPort * inst = 0;
145 OSDictionary * dict;
146
147 IOTakeLock( gIOObjectPortLock);
148
149 do {
150
151 dict = dictForType( type );
152 if( !dict)
153 continue;
154
155 if( (inst = (IOMachPort *)
156 dict->getObject( (const OSSymbol *) obj ))) {
157 inst->mscount++;
158 inst->retain();
159 continue;
160 }
161
162 inst = new IOMachPort;
163 if( inst && !inst->init()) {
164 inst = 0;
165 continue;
166 }
167
168 inst->port = iokit_alloc_object_port( obj, type );
169 if( inst->port) {
170 // retains obj
171 dict->setObject( (const OSSymbol *) obj, inst );
172 inst->mscount++;
173
174 } else {
175 inst->release();
176 inst = 0;
177 }
178
179 } while( false );
180
181 IOUnlock( gIOObjectPortLock);
182
183 return( inst );
184 }
185
186 bool IOMachPort::noMoreSendersForObject( OSObject * obj,
187 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
188 {
189 OSDictionary * dict;
190 IOMachPort * machPort;
191 bool destroyed = true;
192
193 IOTakeLock( gIOObjectPortLock);
194
195 if( (dict = dictForType( type ))) {
196 obj->retain();
197
198 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
199 if( machPort) {
200 destroyed = (machPort->mscount == *mscount);
201 if( destroyed)
202 dict->removeObject( (const OSSymbol *) obj );
203 else
204 *mscount = machPort->mscount;
205 }
206 obj->release();
207 }
208
209 IOUnlock( gIOObjectPortLock);
210
211 return( destroyed );
212 }
213
214 void IOMachPort::releasePortForObject( OSObject * obj,
215 ipc_kobject_type_t type )
216 {
217 OSDictionary * dict;
218 IOMachPort * machPort;
219
220 IOTakeLock( gIOObjectPortLock);
221
222 if( (dict = dictForType( type ))) {
223 obj->retain();
224 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
225 if( machPort && !machPort->holdDestroy)
226 dict->removeObject( (const OSSymbol *) obj );
227 obj->release();
228 }
229
230 IOUnlock( gIOObjectPortLock);
231 }
232
233 void IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type )
234 {
235 OSDictionary * dict;
236 IOMachPort * machPort;
237
238 IOLockLock( gIOObjectPortLock );
239
240 if( (dict = dictForType( type ))) {
241 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
242 if( machPort)
243 machPort->holdDestroy = true;
244 }
245
246 IOLockUnlock( gIOObjectPortLock );
247 }
248
249 void IOUserClient::destroyUserReferences( OSObject * obj )
250 {
251 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
252
253 // panther, 3160200
254 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
255
256 OSDictionary * dict;
257
258 IOTakeLock( gIOObjectPortLock);
259 obj->retain();
260
261 if( (dict = IOMachPort::dictForType( IKOT_IOKIT_CONNECT )))
262 {
263 IOMachPort * port;
264 port = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
265 if (port)
266 {
267 IOUserClient * uc;
268 if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings)
269 {
270 dict->setObject((const OSSymbol *) uc->mappings, port);
271 iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
272
273 uc->mappings->release();
274 uc->mappings = 0;
275 }
276 dict->removeObject( (const OSSymbol *) obj );
277 }
278 }
279 obj->release();
280 IOUnlock( gIOObjectPortLock);
281 }
282
283 mach_port_name_t IOMachPort::makeSendRightForTask( task_t task,
284 io_object_t obj, ipc_kobject_type_t type )
285 {
286 return( iokit_make_send_right( task, obj, type ));
287 }
288
289 void IOMachPort::free( void )
290 {
291 if( port)
292 iokit_destroy_object_port( port );
293 super::free();
294 }
295
296 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
297
298 class IOUserNotification : public OSIterator
299 {
300 OSDeclareDefaultStructors(IOUserNotification)
301
302 IONotifier * holdNotify;
303 IOLock * lock;
304
305 public:
306
307 virtual bool init( void );
308 virtual void free();
309
310 virtual void setNotification( IONotifier * obj );
311
312 virtual void reset();
313 virtual bool isValid();
314 };
315
316 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
317
318 extern "C" {
319
320 // functions called from osfmk/device/iokit_rpc.c
321
322 void
323 iokit_add_reference( io_object_t obj )
324 {
325 if( obj)
326 obj->retain();
327 }
328
329 void
330 iokit_remove_reference( io_object_t obj )
331 {
332 if( obj)
333 obj->release();
334 }
335
336 ipc_port_t
337 iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
338 {
339 IOMachPort * machPort;
340 ipc_port_t port;
341
342 if( (machPort = IOMachPort::portForObject( obj, type ))) {
343
344 port = machPort->port;
345 if( port)
346 iokit_retain_port( port );
347
348 machPort->release();
349
350 } else
351 port = NULL;
352
353 return( port );
354 }
355
356 kern_return_t
357 iokit_client_died( io_object_t obj, ipc_port_t /* port */,
358 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
359 {
360 IOUserClient * client;
361 IOMemoryMap * map;
362 IOUserNotification * notify;
363
364 if( !IOMachPort::noMoreSendersForObject( obj, type, mscount ))
365 return( kIOReturnNotReady );
366
367 if( IKOT_IOKIT_CONNECT == type)
368 {
369 if( (client = OSDynamicCast( IOUserClient, obj )))
370 client->clientDied();
371 }
372 else if( IKOT_IOKIT_OBJECT == type)
373 {
374 if( (map = OSDynamicCast( IOMemoryMap, obj )))
375 map->taskDied();
376 else if( (notify = OSDynamicCast( IOUserNotification, obj )))
377 notify->setNotification( 0 );
378 }
379
380 return( kIOReturnSuccess );
381 }
382
383 }; /* extern "C" */
384
385 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
386
387 class IOServiceUserNotification : public IOUserNotification
388 {
389 OSDeclareDefaultStructors(IOServiceUserNotification)
390
391 struct PingMsg {
392 mach_msg_header_t msgHdr;
393 OSNotificationHeader notifyHeader;
394 };
395
396 enum { kMaxOutstanding = 1024 };
397
398 PingMsg * pingMsg;
399 vm_size_t msgSize;
400 OSArray * newSet;
401 OSObject * lastEntry;
402 bool armed;
403
404 public:
405
406 virtual bool init( mach_port_t port, natural_t type,
407 OSAsyncReference reference );
408 virtual void free();
409
410 static bool _handler( void * target,
411 void * ref, IOService * newService );
412 virtual bool handler( void * ref, IOService * newService );
413
414 virtual OSObject * getNextObject();
415 };
416
417 class IOServiceMessageUserNotification : public IOUserNotification
418 {
419 OSDeclareDefaultStructors(IOServiceMessageUserNotification)
420
421 struct PingMsg {
422 mach_msg_header_t msgHdr;
423 mach_msg_body_t msgBody;
424 mach_msg_port_descriptor_t ports[1];
425 OSNotificationHeader notifyHeader;
426 };
427
428 PingMsg * pingMsg;
429 vm_size_t msgSize;
430
431 public:
432
433 virtual bool init( mach_port_t port, natural_t type,
434 OSAsyncReference reference, vm_size_t extraSize );
435 virtual void free();
436
437 static IOReturn _handler( void * target, void * ref,
438 UInt32 messageType, IOService * provider,
439 void * messageArgument, vm_size_t argSize );
440 virtual IOReturn handler( void * ref,
441 UInt32 messageType, IOService * provider,
442 void * messageArgument, vm_size_t argSize );
443
444 virtual OSObject * getNextObject();
445 };
446
447 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
448
449 #undef super
450 #define super OSIterator
451 OSDefineMetaClass( IOUserNotification, OSIterator )
452 OSDefineAbstractStructors( IOUserNotification, OSIterator )
453
454 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
455
456 bool IOUserNotification::init( void )
457 {
458 if( !super::init())
459 return( false );
460
461 lock = IOLockAlloc();
462 if( !lock)
463 return( false );
464
465 return( true );
466 }
467
468 void IOUserNotification::free( void )
469 {
470 if( holdNotify)
471 holdNotify->remove();
472 // can't be in handler now
473
474 if( lock)
475 IOLockFree( lock );
476
477 super::free();
478 }
479
480
481 void IOUserNotification::setNotification( IONotifier * notify )
482 {
483 IONotifier * previousNotify;
484
485 IOLockLock( gIOObjectPortLock);
486
487 previousNotify = holdNotify;
488 holdNotify = notify;
489
490 IOLockUnlock( gIOObjectPortLock);
491
492 if( previousNotify)
493 previousNotify->remove();
494 }
495
496 void IOUserNotification::reset()
497 {
498 // ?
499 }
500
501 bool IOUserNotification::isValid()
502 {
503 return( true );
504 }
505
506 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
507
508 #undef super
509 #define super IOUserNotification
510 OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
511
512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
513
514 bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
515 OSAsyncReference reference )
516 {
517 newSet = OSArray::withCapacity( 1 );
518 if( !newSet)
519 return( false );
520
521 msgSize = sizeof( PingMsg) + 0;
522 pingMsg = (PingMsg *) IOMalloc( msgSize);
523 if( !pingMsg)
524 return( false );
525
526 bzero( pingMsg, msgSize);
527
528 pingMsg->msgHdr.msgh_remote_port = port;
529 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS(
530 MACH_MSG_TYPE_COPY_SEND /*remote*/,
531 MACH_MSG_TYPE_MAKE_SEND /*local*/);
532 pingMsg->msgHdr.msgh_size = msgSize;
533 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
534
535 pingMsg->notifyHeader.size = 0;
536 pingMsg->notifyHeader.type = type;
537 bcopy( reference, pingMsg->notifyHeader.reference, sizeof(OSAsyncReference) );
538
539 return( super::init() );
540 }
541
542 void IOServiceUserNotification::free( void )
543 {
544 PingMsg * _pingMsg;
545 vm_size_t _msgSize;
546 OSArray * _newSet;
547 OSObject * _lastEntry;
548
549 _pingMsg = pingMsg;
550 _msgSize = msgSize;
551 _lastEntry = lastEntry;
552 _newSet = newSet;
553
554 super::free();
555
556 if( _pingMsg && _msgSize)
557 IOFree( _pingMsg, _msgSize);
558
559 if( _lastEntry)
560 _lastEntry->release();
561
562 if( _newSet)
563 _newSet->release();
564 }
565
566 bool IOServiceUserNotification::_handler( void * target,
567 void * ref, IOService * newService )
568 {
569 return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
570 }
571
572 bool IOServiceUserNotification::handler( void * ref,
573 IOService * newService )
574 {
575 unsigned int count;
576 kern_return_t kr;
577 ipc_port_t port = NULL;
578 bool sendPing = false;
579
580 IOTakeLock( lock );
581
582 count = newSet->getCount();
583 if( count < kMaxOutstanding) {
584
585 newSet->setObject( newService );
586 if( (sendPing = (armed && (0 == count))))
587 armed = false;
588 }
589
590 IOUnlock( lock );
591
592 if( kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type)
593 IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT );
594
595 if( sendPing) {
596 if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) ))
597 pingMsg->msgHdr.msgh_local_port = port;
598 else
599 pingMsg->msgHdr.msgh_local_port = NULL;
600
601 kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
602 pingMsg->msgHdr.msgh_size);
603 if( port)
604 iokit_release_port( port );
605
606 if( KERN_SUCCESS != kr)
607 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
608 }
609
610 return( true );
611 }
612
613 OSObject * IOServiceUserNotification::getNextObject()
614 {
615 unsigned int count;
616 OSObject * result;
617
618 IOTakeLock( lock );
619
620 if( lastEntry)
621 lastEntry->release();
622
623 count = newSet->getCount();
624 if( count ) {
625 result = newSet->getObject( count - 1 );
626 result->retain();
627 newSet->removeObject( count - 1);
628 } else {
629 result = 0;
630 armed = true;
631 }
632 lastEntry = result;
633
634 IOUnlock( lock );
635
636 return( result );
637 }
638
639 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
640
641 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
642
643 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
644
645 bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
646 OSAsyncReference reference, vm_size_t extraSize )
647 {
648
649 extraSize += sizeof(IOServiceInterestContent);
650 msgSize = sizeof( PingMsg) + extraSize;
651 pingMsg = (PingMsg *) IOMalloc( msgSize);
652 if( !pingMsg)
653 return( false );
654
655 bzero( pingMsg, msgSize);
656
657 pingMsg->msgHdr.msgh_remote_port = port;
658 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS_COMPLEX
659 | MACH_MSGH_BITS(
660 MACH_MSG_TYPE_COPY_SEND /*remote*/,
661 MACH_MSG_TYPE_MAKE_SEND /*local*/);
662 pingMsg->msgHdr.msgh_size = msgSize;
663 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
664
665 pingMsg->msgBody.msgh_descriptor_count = 1;
666
667 pingMsg->ports[0].name = 0;
668 pingMsg->ports[0].disposition = MACH_MSG_TYPE_MAKE_SEND;
669 pingMsg->ports[0].type = MACH_MSG_PORT_DESCRIPTOR;
670
671 pingMsg->notifyHeader.size = extraSize;
672 pingMsg->notifyHeader.type = type;
673 bcopy( reference, pingMsg->notifyHeader.reference, sizeof(OSAsyncReference) );
674
675 return( super::init() );
676 }
677
678 void IOServiceMessageUserNotification::free( void )
679 {
680 PingMsg * _pingMsg;
681 vm_size_t _msgSize;
682
683 _pingMsg = pingMsg;
684 _msgSize = msgSize;
685
686 super::free();
687
688 if( _pingMsg && _msgSize)
689 IOFree( _pingMsg, _msgSize);
690 }
691
692 IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
693 UInt32 messageType, IOService * provider,
694 void * argument, vm_size_t argSize )
695 {
696 return( ((IOServiceMessageUserNotification *) target)->handler(
697 ref, messageType, provider, argument, argSize));
698 }
699
700 IOReturn IOServiceMessageUserNotification::handler( void * ref,
701 UInt32 messageType, IOService * provider,
702 void * messageArgument, vm_size_t argSize )
703 {
704 kern_return_t kr;
705 ipc_port_t thisPort, providerPort;
706 IOServiceInterestContent * data = (IOServiceInterestContent *)
707 pingMsg->notifyHeader.content;
708
709 data->messageType = messageType;
710 if( argSize == 0) {
711 argSize = sizeof( messageArgument);
712 data->messageArgument[0] = messageArgument;
713 } else {
714 if( argSize > kIOUserNotifyMaxMessageSize)
715 argSize = kIOUserNotifyMaxMessageSize;
716 bcopy( messageArgument, data->messageArgument, argSize );
717 }
718 pingMsg->msgHdr.msgh_size = sizeof( PingMsg)
719 + sizeof( IOServiceInterestContent )
720 - sizeof( data->messageArgument)
721 + argSize;
722
723 providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
724 pingMsg->ports[0].name = providerPort;
725 thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
726 pingMsg->msgHdr.msgh_local_port = thisPort;
727 kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
728 pingMsg->msgHdr.msgh_size);
729 if( thisPort)
730 iokit_release_port( thisPort );
731 if( providerPort)
732 iokit_release_port( providerPort );
733
734 if( KERN_SUCCESS != kr)
735 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
736
737 return( kIOReturnSuccess );
738 }
739
740 OSObject * IOServiceMessageUserNotification::getNextObject()
741 {
742 return( 0 );
743 }
744
745 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
746
747 #undef super
748 #define super IOService
749 OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
750
751 void IOUserClient::initialize( void )
752 {
753 gIOObjectPortLock = IOLockAlloc();
754
755 assert( gIOObjectPortLock );
756 }
757
758 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
759 mach_port_t wakePort,
760 void *callback, void *refcon)
761 {
762 asyncRef[kIOAsyncReservedIndex] = (natural_t) wakePort;
763 asyncRef[kIOAsyncCalloutFuncIndex] = (natural_t) callback;
764 asyncRef[kIOAsyncCalloutRefconIndex] = (natural_t) refcon;
765 }
766
767 inline OSDictionary * CopyConsoleUser(UInt32 uid)
768 {
769 OSArray * array;
770 OSDictionary * user = 0;
771
772 if ((array = OSDynamicCast(OSArray,
773 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
774 {
775 for (unsigned int idx = 0;
776 (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
777 idx++) {
778 OSNumber * num;
779
780 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
781 && (uid == num->unsigned32BitValue())) {
782 user->retain();
783 break;
784 }
785 }
786 array->release();
787 }
788 return user;
789 }
790
791 IOReturn IOUserClient::clientHasPrivilege( void * securityToken,
792 const char * privilegeName )
793 {
794 kern_return_t kr;
795 security_token_t token;
796 mach_msg_type_number_t count;
797 task_t task;
798 OSDictionary * user;
799 bool secureConsole;
800
801 if ((secureConsole = !strcmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess)))
802 task = (task_t)((IOUCProcessToken *)securityToken)->token;
803 else
804 task = (task_t)securityToken;
805
806 count = TASK_SECURITY_TOKEN_COUNT;
807 kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count );
808
809 if (KERN_SUCCESS != kr)
810 {}
811 else if (!strcmp(privilegeName, kIOClientPrivilegeAdministrator)) {
812 if (0 != token.val[0])
813 kr = kIOReturnNotPrivileged;
814 } else if (!strcmp(privilegeName, kIOClientPrivilegeLocalUser)) {
815 user = CopyConsoleUser(token.val[0]);
816 if ( user )
817 user->release();
818 else
819 kr = kIOReturnNotPrivileged;
820 } else if (secureConsole || !strcmp(privilegeName, kIOClientPrivilegeConsoleUser)) {
821 user = CopyConsoleUser(token.val[0]);
822 if ( user ) {
823 if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue)
824 kr = kIOReturnNotPrivileged;
825 else if ( secureConsole ) {
826 OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey));
827 if ( pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid)
828 kr = kIOReturnNotPrivileged;
829 }
830 user->release();
831 }
832 else
833 kr = kIOReturnNotPrivileged;
834 } else
835 kr = kIOReturnUnsupported;
836
837 return (kr);
838 }
839
840 bool IOUserClient::initWithTask(task_t owningTask,
841 void * securityID,
842 UInt32 type )
843 {
844 if( getPropertyTable())
845 return true;
846 else
847 return super::init();
848 }
849
850 bool IOUserClient::initWithTask(task_t owningTask,
851 void * securityID,
852 UInt32 type,
853 OSDictionary * properties )
854 {
855 bool ok;
856
857 ok = super::init( properties );
858 ok &= initWithTask( owningTask, securityID, type );
859
860 return( ok );
861 }
862
863 void IOUserClient::free()
864 {
865 if( mappings)
866 mappings->release();
867
868 super::free();
869 }
870
871 IOReturn IOUserClient::clientDied( void )
872 {
873 return( clientClose());
874 }
875
876 IOReturn IOUserClient::clientClose( void )
877 {
878 return( kIOReturnUnsupported );
879 }
880
881 IOService * IOUserClient::getService( void )
882 {
883 return( 0 );
884 }
885
886 IOReturn IOUserClient::registerNotificationPort(
887 mach_port_t /* port */,
888 UInt32 /* type */,
889 UInt32 /* refCon */)
890 {
891 return( kIOReturnUnsupported);
892 }
893
894 IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
895 semaphore_t * semaphore )
896 {
897 return( kIOReturnUnsupported);
898 }
899
900 IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
901 {
902 return( kIOReturnUnsupported);
903 }
904
905 IOReturn IOUserClient::clientMemoryForType( UInt32 type,
906 IOOptionBits * options,
907 IOMemoryDescriptor ** memory )
908 {
909 return( kIOReturnUnsupported);
910 }
911
912 IOMemoryMap * IOUserClient::mapClientMemory(
913 IOOptionBits type,
914 task_t task,
915 IOOptionBits mapFlags,
916 IOVirtualAddress atAddress )
917 {
918 IOReturn err;
919 IOOptionBits options = 0;
920 IOMemoryDescriptor * memory;
921 IOMemoryMap * map = 0;
922
923 err = clientMemoryForType( (UInt32) type, &options, &memory );
924
925 if( memory && (kIOReturnSuccess == err)) {
926
927 options = (options & ~kIOMapUserOptionsMask)
928 | (mapFlags & kIOMapUserOptionsMask);
929 map = memory->map( task, atAddress, options );
930 memory->release();
931 }
932
933 return( map );
934 }
935
936 IOReturn IOUserClient::exportObjectToClient(task_t task,
937 OSObject *obj, io_object_t *clientObj)
938 {
939 mach_port_name_t name;
940
941 name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
942 assert( name );
943
944 *(mach_port_name_t *)clientObj = name;
945 return kIOReturnSuccess;
946 }
947
948 IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
949 {
950 return( 0 );
951 }
952
953 IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
954 {
955 return( 0 );
956 }
957
958 IOExternalMethod * IOUserClient::
959 getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
960 {
961 IOExternalMethod *method = getExternalMethodForIndex(index);
962
963 if (method)
964 *targetP = (IOService *) method->object;
965
966 return method;
967 }
968
969 IOExternalAsyncMethod * IOUserClient::
970 getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
971 {
972 IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
973
974 if (method)
975 *targetP = (IOService *) method->object;
976
977 return method;
978 }
979
980 IOExternalTrap * IOUserClient::
981 getExternalTrapForIndex(UInt32 index)
982 {
983 return NULL;
984 }
985
986 IOExternalTrap * IOUserClient::
987 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
988 {
989 IOExternalTrap *trap = getExternalTrapForIndex(index);
990
991 if (trap) {
992 *targetP = trap->object;
993 }
994
995 return trap;
996 }
997
998 IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
999 IOReturn result, void *args[], UInt32 numArgs)
1000 {
1001 struct ReplyMsg {
1002 mach_msg_header_t msgHdr;
1003 OSNotificationHeader notifyHdr;
1004 IOAsyncCompletionContent asyncContent;
1005 void * args[kMaxAsyncArgs];
1006 };
1007 ReplyMsg replyMsg;
1008 mach_port_t replyPort;
1009 kern_return_t kr;
1010
1011 // If no reply port, do nothing.
1012 replyPort = (mach_port_t) reference[0];
1013 if(replyPort == MACH_PORT_NULL)
1014 return kIOReturnSuccess;
1015
1016 if(numArgs > kMaxAsyncArgs)
1017 return kIOReturnMessageTooLarge;
1018 replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
1019 0 /*local*/);
1020 replyMsg.msgHdr.msgh_size =
1021 sizeof(replyMsg) - (kMaxAsyncArgs-numArgs)*sizeof(void *);
1022 replyMsg.msgHdr.msgh_remote_port = replyPort;
1023 replyMsg.msgHdr.msgh_local_port = 0;
1024 replyMsg.msgHdr.msgh_id = kOSNotificationMessageID;
1025
1026 replyMsg.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1027 + numArgs*sizeof(void *);
1028 replyMsg.notifyHdr.type = kIOAsyncCompletionNotificationType;
1029 bcopy( reference, replyMsg.notifyHdr.reference, sizeof(OSAsyncReference));
1030
1031 replyMsg.asyncContent.result = result;
1032 if(numArgs > 0)
1033 bcopy(args, replyMsg.args, sizeof(void *)*numArgs);
1034 kr = mach_msg_send_from_kernel( &replyMsg.msgHdr,
1035 replyMsg.msgHdr.msgh_size);
1036 if( KERN_SUCCESS != kr)
1037 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
1038 return kr;
1039 }
1040
1041 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1042
1043 extern "C" {
1044
1045 #define CHECK(cls,obj,out) \
1046 cls * out; \
1047 if( !(out = OSDynamicCast( cls, obj))) \
1048 return( kIOReturnBadArgument )
1049
1050 /* Routine io_object_get_class */
1051 kern_return_t is_io_object_get_class(
1052 io_object_t object,
1053 io_name_t className )
1054 {
1055 const OSMetaClass* my_obj = NULL;
1056
1057 if( !object)
1058 return( kIOReturnBadArgument );
1059
1060 my_obj = object->getMetaClass();
1061 if (!my_obj) {
1062 return (kIOReturnNotFound);
1063 }
1064
1065 strcpy( className, my_obj->getClassName());
1066 return( kIOReturnSuccess );
1067 }
1068
1069 /* Routine io_object_get_superclass */
1070 kern_return_t is_io_object_get_superclass(
1071 mach_port_t master_port,
1072 io_name_t obj_name,
1073 io_name_t class_name)
1074 {
1075 const OSMetaClass* my_obj = NULL;
1076 const OSMetaClass* superclass = NULL;
1077 const OSSymbol *my_name = NULL;
1078 const char *my_cstr = NULL;
1079
1080 if (!obj_name || !class_name)
1081 return (kIOReturnBadArgument);
1082
1083 if( master_port != master_device_port)
1084 return( kIOReturnNotPrivileged);
1085
1086 my_name = OSSymbol::withCString(obj_name);
1087
1088 if (my_name) {
1089 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1090 my_name->release();
1091 }
1092 if (my_obj) {
1093 superclass = my_obj->getSuperClass();
1094 }
1095
1096 if (!superclass) {
1097 return( kIOReturnNotFound );
1098 }
1099
1100 my_cstr = superclass->getClassName();
1101
1102 if (my_cstr) {
1103 strncpy(class_name, my_cstr, sizeof(io_name_t)-1);
1104 return( kIOReturnSuccess );
1105 }
1106 return (kIOReturnNotFound);
1107 }
1108
1109 /* Routine io_object_get_bundle_identifier */
1110 kern_return_t is_io_object_get_bundle_identifier(
1111 mach_port_t master_port,
1112 io_name_t obj_name,
1113 io_name_t bundle_name)
1114 {
1115 const OSMetaClass* my_obj = NULL;
1116 const OSSymbol *my_name = NULL;
1117 const OSSymbol *identifier = NULL;
1118 const char *my_cstr = NULL;
1119
1120 if (!obj_name || !bundle_name)
1121 return (kIOReturnBadArgument);
1122
1123 if( master_port != master_device_port)
1124 return( kIOReturnNotPrivileged);
1125
1126 my_name = OSSymbol::withCString(obj_name);
1127
1128 if (my_name) {
1129 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1130 my_name->release();
1131 }
1132
1133 if (my_obj) {
1134 identifier = my_obj->getKmodName();
1135 }
1136 if (!identifier) {
1137 return( kIOReturnNotFound );
1138 }
1139
1140 my_cstr = identifier->getCStringNoCopy();
1141 if (my_cstr) {
1142 strncpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t)-1);
1143 return( kIOReturnSuccess );
1144 }
1145
1146 return (kIOReturnBadArgument);
1147 }
1148
1149 /* Routine io_object_conforms_to */
1150 kern_return_t is_io_object_conforms_to(
1151 io_object_t object,
1152 io_name_t className,
1153 boolean_t *conforms )
1154 {
1155 if( !object)
1156 return( kIOReturnBadArgument );
1157
1158 *conforms = (0 != object->metaCast( className ));
1159 return( kIOReturnSuccess );
1160 }
1161
1162 /* Routine io_object_get_retain_count */
1163 kern_return_t is_io_object_get_retain_count(
1164 io_object_t object,
1165 int *retainCount )
1166 {
1167 if( !object)
1168 return( kIOReturnBadArgument );
1169
1170 *retainCount = object->getRetainCount();
1171 return( kIOReturnSuccess );
1172 }
1173
1174 /* Routine io_iterator_next */
1175 kern_return_t is_io_iterator_next(
1176 io_object_t iterator,
1177 io_object_t *object )
1178 {
1179 OSObject * obj;
1180
1181 CHECK( OSIterator, iterator, iter );
1182
1183 obj = iter->getNextObject();
1184 if( obj) {
1185 obj->retain();
1186 *object = obj;
1187 return( kIOReturnSuccess );
1188 } else
1189 return( kIOReturnNoDevice );
1190 }
1191
1192 /* Routine io_iterator_reset */
1193 kern_return_t is_io_iterator_reset(
1194 io_object_t iterator )
1195 {
1196 CHECK( OSIterator, iterator, iter );
1197
1198 iter->reset();
1199
1200 return( kIOReturnSuccess );
1201 }
1202
1203 /* Routine io_iterator_is_valid */
1204 kern_return_t is_io_iterator_is_valid(
1205 io_object_t iterator,
1206 boolean_t *is_valid )
1207 {
1208 CHECK( OSIterator, iterator, iter );
1209
1210 *is_valid = iter->isValid();
1211
1212 return( kIOReturnSuccess );
1213 }
1214
1215 /* Routine io_service_match_property_table */
1216 kern_return_t is_io_service_match_property_table(
1217 io_service_t _service,
1218 io_string_t matching,
1219 boolean_t *matches )
1220 {
1221 CHECK( IOService, _service, service );
1222
1223 kern_return_t kr;
1224 OSObject * obj;
1225 OSDictionary * dict;
1226
1227 obj = OSUnserializeXML( matching );
1228
1229 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1230 *matches = service->passiveMatch( dict );
1231 kr = kIOReturnSuccess;
1232 } else
1233 kr = kIOReturnBadArgument;
1234
1235 if( obj)
1236 obj->release();
1237
1238 return( kr );
1239 }
1240
1241 /* Routine io_service_match_property_table_ool */
1242 kern_return_t is_io_service_match_property_table_ool(
1243 io_object_t service,
1244 io_buf_ptr_t matching,
1245 mach_msg_type_number_t matchingCnt,
1246 natural_t *result,
1247 boolean_t *matches )
1248 {
1249 kern_return_t kr;
1250 vm_offset_t data;
1251 vm_map_offset_t map_data;
1252
1253 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1254 data = CAST_DOWN(vm_offset_t, map_data);
1255
1256 if( KERN_SUCCESS == kr) {
1257 // must return success after vm_map_copyout() succeeds
1258 *result = is_io_service_match_property_table( service,
1259 (char *) data, matches );
1260 vm_deallocate( kernel_map, data, matchingCnt );
1261 }
1262
1263 return( kr );
1264 }
1265
1266 /* Routine io_service_get_matching_services */
1267 kern_return_t is_io_service_get_matching_services(
1268 mach_port_t master_port,
1269 io_string_t matching,
1270 io_iterator_t *existing )
1271 {
1272 kern_return_t kr;
1273 OSObject * obj;
1274 OSDictionary * dict;
1275
1276 if( master_port != master_device_port)
1277 return( kIOReturnNotPrivileged);
1278
1279 obj = OSUnserializeXML( matching );
1280
1281 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1282 *existing = IOService::getMatchingServices( dict );
1283 kr = kIOReturnSuccess;
1284 } else
1285 kr = kIOReturnBadArgument;
1286
1287 if( obj)
1288 obj->release();
1289
1290 return( kr );
1291 }
1292
1293 /* Routine io_service_get_matching_services_ool */
1294 kern_return_t is_io_service_get_matching_services_ool(
1295 mach_port_t master_port,
1296 io_buf_ptr_t matching,
1297 mach_msg_type_number_t matchingCnt,
1298 natural_t *result,
1299 io_object_t *existing )
1300 {
1301 kern_return_t kr;
1302 vm_offset_t data;
1303 vm_map_offset_t map_data;
1304
1305 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1306 data = CAST_DOWN(vm_offset_t, map_data);
1307
1308 if( KERN_SUCCESS == kr) {
1309 // must return success after vm_map_copyout() succeeds
1310 *result = is_io_service_get_matching_services( master_port,
1311 (char *) data, existing );
1312 vm_deallocate( kernel_map, data, matchingCnt );
1313 }
1314
1315 return( kr );
1316 }
1317
1318 /* Routine io_service_add_notification */
1319 kern_return_t is_io_service_add_notification(
1320 mach_port_t master_port,
1321 io_name_t notification_type,
1322 io_string_t matching,
1323 mach_port_t port,
1324 io_async_ref_t reference,
1325 mach_msg_type_number_t referenceCnt,
1326 io_object_t * notification )
1327 {
1328 IOServiceUserNotification * userNotify = 0;
1329 IONotifier * notify = 0;
1330 const OSSymbol * sym;
1331 OSDictionary * dict;
1332 IOReturn err;
1333 unsigned long int userMsgType;
1334
1335
1336 if( master_port != master_device_port)
1337 return( kIOReturnNotPrivileged);
1338
1339 do {
1340 err = kIOReturnNoResources;
1341
1342 if( !(sym = OSSymbol::withCString( notification_type )))
1343 err = kIOReturnNoResources;
1344
1345 if( !(dict = OSDynamicCast( OSDictionary,
1346 OSUnserializeXML( matching )))) {
1347 err = kIOReturnBadArgument;
1348 continue;
1349 }
1350
1351 if( (sym == gIOPublishNotification)
1352 || (sym == gIOFirstPublishNotification))
1353 userMsgType = kIOServicePublishNotificationType;
1354 else if( (sym == gIOMatchedNotification)
1355 || (sym == gIOFirstMatchNotification))
1356 userMsgType = kIOServiceMatchedNotificationType;
1357 else if( sym == gIOTerminatedNotification)
1358 userMsgType = kIOServiceTerminatedNotificationType;
1359 else
1360 userMsgType = kLastIOKitNotificationType;
1361
1362 userNotify = new IOServiceUserNotification;
1363
1364 if( userNotify && !userNotify->init( port, userMsgType,
1365 reference)) {
1366 userNotify->release();
1367 userNotify = 0;
1368 }
1369 if( !userNotify)
1370 continue;
1371
1372 notify = IOService::addNotification( sym, dict,
1373 &userNotify->_handler, userNotify );
1374 if( notify) {
1375 dict = 0;
1376 *notification = userNotify;
1377 userNotify->setNotification( notify );
1378 err = kIOReturnSuccess;
1379 } else
1380 err = kIOReturnUnsupported;
1381
1382 } while( false );
1383
1384 if( sym)
1385 sym->release();
1386 if( dict)
1387 dict->release();
1388
1389 return( err );
1390 }
1391
1392 /* Routine io_service_add_notification_ool */
1393 kern_return_t is_io_service_add_notification_ool(
1394 mach_port_t master_port,
1395 io_name_t notification_type,
1396 io_buf_ptr_t matching,
1397 mach_msg_type_number_t matchingCnt,
1398 mach_port_t wake_port,
1399 io_async_ref_t reference,
1400 mach_msg_type_number_t referenceCnt,
1401 natural_t *result,
1402 io_object_t *notification )
1403 {
1404 kern_return_t kr;
1405 vm_offset_t data;
1406 vm_map_offset_t map_data;
1407
1408 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1409 data = CAST_DOWN(vm_offset_t, map_data);
1410
1411 if( KERN_SUCCESS == kr) {
1412 // must return success after vm_map_copyout() succeeds
1413 *result = is_io_service_add_notification( master_port, notification_type,
1414 (char *) data, wake_port, reference, referenceCnt, notification );
1415 vm_deallocate( kernel_map, data, matchingCnt );
1416 }
1417
1418 return( kr );
1419 }
1420
1421
1422 /* Routine io_service_add_notification_old */
1423 kern_return_t is_io_service_add_notification_old(
1424 mach_port_t master_port,
1425 io_name_t notification_type,
1426 io_string_t matching,
1427 mach_port_t port,
1428 natural_t ref,
1429 io_object_t * notification )
1430 {
1431 return( is_io_service_add_notification( master_port, notification_type,
1432 matching, port, &ref, 1, notification ));
1433 }
1434
1435 /* Routine io_service_add_message_notification */
1436 kern_return_t is_io_service_add_interest_notification(
1437 io_object_t _service,
1438 io_name_t type_of_interest,
1439 mach_port_t port,
1440 io_async_ref_t reference,
1441 mach_msg_type_number_t referenceCnt,
1442 io_object_t * notification )
1443 {
1444
1445 IOServiceMessageUserNotification * userNotify = 0;
1446 IONotifier * notify = 0;
1447 const OSSymbol * sym;
1448 IOReturn err;
1449
1450 CHECK( IOService, _service, service );
1451
1452 err = kIOReturnNoResources;
1453 if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1454
1455 userNotify = new IOServiceMessageUserNotification;
1456
1457 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
1458 reference, kIOUserNotifyMaxMessageSize )) {
1459 userNotify->release();
1460 userNotify = 0;
1461 }
1462 if( !userNotify)
1463 continue;
1464
1465 notify = service->registerInterest( sym,
1466 &userNotify->_handler, userNotify );
1467 if( notify) {
1468 *notification = userNotify;
1469 userNotify->setNotification( notify );
1470 err = kIOReturnSuccess;
1471 } else
1472 err = kIOReturnUnsupported;
1473
1474 sym->release();
1475
1476 } while( false );
1477
1478 return( err );
1479 }
1480
1481 /* Routine io_service_acknowledge_notification */
1482 kern_return_t is_io_service_acknowledge_notification(
1483 io_object_t _service,
1484 natural_t notify_ref,
1485 natural_t response )
1486 {
1487 CHECK( IOService, _service, service );
1488
1489 return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1490 (IOOptionBits) response ));
1491
1492 }
1493
1494 /* Routine io_connect_get_semaphore */
1495 kern_return_t is_io_connect_get_notification_semaphore(
1496 io_connect_t connection,
1497 natural_t notification_type,
1498 semaphore_t *semaphore )
1499 {
1500 CHECK( IOUserClient, connection, client );
1501
1502 return( client->getNotificationSemaphore( (UInt32) notification_type,
1503 semaphore ));
1504 }
1505
1506 /* Routine io_registry_get_root_entry */
1507 kern_return_t is_io_registry_get_root_entry(
1508 mach_port_t master_port,
1509 io_object_t *root )
1510 {
1511 IORegistryEntry * entry;
1512
1513 if( master_port != master_device_port)
1514 return( kIOReturnNotPrivileged);
1515
1516 entry = IORegistryEntry::getRegistryRoot();
1517 if( entry)
1518 entry->retain();
1519 *root = entry;
1520
1521 return( kIOReturnSuccess );
1522 }
1523
1524 /* Routine io_registry_create_iterator */
1525 kern_return_t is_io_registry_create_iterator(
1526 mach_port_t master_port,
1527 io_name_t plane,
1528 int options,
1529 io_object_t *iterator )
1530 {
1531 if( master_port != master_device_port)
1532 return( kIOReturnNotPrivileged);
1533
1534 *iterator = IORegistryIterator::iterateOver(
1535 IORegistryEntry::getPlane( plane ), options );
1536
1537 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1538 }
1539
1540 /* Routine io_registry_entry_create_iterator */
1541 kern_return_t is_io_registry_entry_create_iterator(
1542 io_object_t registry_entry,
1543 io_name_t plane,
1544 int options,
1545 io_object_t *iterator )
1546 {
1547 CHECK( IORegistryEntry, registry_entry, entry );
1548
1549 *iterator = IORegistryIterator::iterateOver( entry,
1550 IORegistryEntry::getPlane( plane ), options );
1551
1552 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1553 }
1554
1555 /* Routine io_registry_iterator_enter */
1556 kern_return_t is_io_registry_iterator_enter_entry(
1557 io_object_t iterator )
1558 {
1559 CHECK( IORegistryIterator, iterator, iter );
1560
1561 iter->enterEntry();
1562
1563 return( kIOReturnSuccess );
1564 }
1565
1566 /* Routine io_registry_iterator_exit */
1567 kern_return_t is_io_registry_iterator_exit_entry(
1568 io_object_t iterator )
1569 {
1570 bool didIt;
1571
1572 CHECK( IORegistryIterator, iterator, iter );
1573
1574 didIt = iter->exitEntry();
1575
1576 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
1577 }
1578
1579 /* Routine io_registry_entry_from_path */
1580 kern_return_t is_io_registry_entry_from_path(
1581 mach_port_t master_port,
1582 io_string_t path,
1583 io_object_t *registry_entry )
1584 {
1585 IORegistryEntry * entry;
1586
1587 if( master_port != master_device_port)
1588 return( kIOReturnNotPrivileged);
1589
1590 entry = IORegistryEntry::fromPath( path );
1591
1592 *registry_entry = entry;
1593
1594 return( kIOReturnSuccess );
1595 }
1596
1597 /* Routine io_registry_entry_in_plane */
1598 kern_return_t is_io_registry_entry_in_plane(
1599 io_object_t registry_entry,
1600 io_name_t plane,
1601 boolean_t *inPlane )
1602 {
1603 CHECK( IORegistryEntry, registry_entry, entry );
1604
1605 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
1606
1607 return( kIOReturnSuccess );
1608 }
1609
1610
1611 /* Routine io_registry_entry_get_path */
1612 kern_return_t is_io_registry_entry_get_path(
1613 io_object_t registry_entry,
1614 io_name_t plane,
1615 io_string_t path )
1616 {
1617 int length;
1618 CHECK( IORegistryEntry, registry_entry, entry );
1619
1620 length = sizeof( io_string_t);
1621 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
1622 return( kIOReturnSuccess );
1623 else
1624 return( kIOReturnBadArgument );
1625 }
1626
1627
1628 /* Routine io_registry_entry_get_name */
1629 kern_return_t is_io_registry_entry_get_name(
1630 io_object_t registry_entry,
1631 io_name_t name )
1632 {
1633 CHECK( IORegistryEntry, registry_entry, entry );
1634
1635 strncpy( name, entry->getName(), sizeof( io_name_t));
1636
1637 return( kIOReturnSuccess );
1638 }
1639
1640 /* Routine io_registry_entry_get_name_in_plane */
1641 kern_return_t is_io_registry_entry_get_name_in_plane(
1642 io_object_t registry_entry,
1643 io_name_t planeName,
1644 io_name_t name )
1645 {
1646 const IORegistryPlane * plane;
1647 CHECK( IORegistryEntry, registry_entry, entry );
1648
1649 if( planeName[0])
1650 plane = IORegistryEntry::getPlane( planeName );
1651 else
1652 plane = 0;
1653
1654 strncpy( name, entry->getName( plane), sizeof( io_name_t));
1655
1656 return( kIOReturnSuccess );
1657 }
1658
1659 /* Routine io_registry_entry_get_location_in_plane */
1660 kern_return_t is_io_registry_entry_get_location_in_plane(
1661 io_object_t registry_entry,
1662 io_name_t planeName,
1663 io_name_t location )
1664 {
1665 const IORegistryPlane * plane;
1666 CHECK( IORegistryEntry, registry_entry, entry );
1667
1668 if( planeName[0])
1669 plane = IORegistryEntry::getPlane( planeName );
1670 else
1671 plane = 0;
1672
1673 const char * cstr = entry->getLocation( plane );
1674
1675 if( cstr) {
1676 strncpy( location, cstr, sizeof( io_name_t));
1677 return( kIOReturnSuccess );
1678 } else
1679 return( kIOReturnNotFound );
1680 }
1681
1682 // Create a vm_map_copy_t or kalloc'ed data for memory
1683 // to be copied out. ipc will free after the copyout.
1684
1685 static kern_return_t copyoutkdata( void * data, vm_size_t len,
1686 io_buf_ptr_t * buf )
1687 {
1688 kern_return_t err;
1689 vm_map_copy_t copy;
1690
1691 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
1692 false /* src_destroy */, &copy);
1693
1694 assert( err == KERN_SUCCESS );
1695 if( err == KERN_SUCCESS )
1696 *buf = (char *) copy;
1697
1698 return( err );
1699 }
1700
1701 /* Routine io_registry_entry_get_property */
1702 kern_return_t is_io_registry_entry_get_property_bytes(
1703 io_object_t registry_entry,
1704 io_name_t property_name,
1705 io_scalar_inband_t buf,
1706 mach_msg_type_number_t *dataCnt )
1707 {
1708 OSObject * obj;
1709 OSData * data;
1710 OSString * str;
1711 OSBoolean * boo;
1712 OSNumber * off;
1713 UInt64 offsetBytes;
1714 unsigned int len = 0;
1715 const void * bytes = 0;
1716 IOReturn ret = kIOReturnSuccess;
1717
1718 CHECK( IORegistryEntry, registry_entry, entry );
1719
1720 obj = entry->copyProperty(property_name);
1721 if( !obj)
1722 return( kIOReturnNoResources );
1723
1724 // One day OSData will be a common container base class
1725 // until then...
1726 if( (data = OSDynamicCast( OSData, obj ))) {
1727 len = data->getLength();
1728 bytes = data->getBytesNoCopy();
1729
1730 } else if( (str = OSDynamicCast( OSString, obj ))) {
1731 len = str->getLength() + 1;
1732 bytes = str->getCStringNoCopy();
1733
1734 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
1735 len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
1736 bytes = boo->isTrue() ? "Yes" : "No";
1737
1738 } else if( (off = OSDynamicCast( OSNumber, obj ))) {
1739 offsetBytes = off->unsigned64BitValue();
1740 len = off->numberOfBytes();
1741 bytes = &offsetBytes;
1742 #ifdef __BIG_ENDIAN__
1743 bytes = (const void *)
1744 (((UInt32) bytes) + (sizeof( UInt64) - len));
1745 #endif
1746
1747 } else
1748 ret = kIOReturnBadArgument;
1749
1750 if( bytes) {
1751 if( *dataCnt < len)
1752 ret = kIOReturnIPCError;
1753 else {
1754 *dataCnt = len;
1755 bcopy( bytes, buf, len );
1756 }
1757 }
1758 obj->release();
1759
1760 return( ret );
1761 }
1762
1763 /* Routine io_registry_entry_get_property */
1764 kern_return_t is_io_registry_entry_get_property(
1765 io_object_t registry_entry,
1766 io_name_t property_name,
1767 io_buf_ptr_t *properties,
1768 mach_msg_type_number_t *propertiesCnt )
1769 {
1770 kern_return_t err;
1771 vm_size_t len;
1772 OSObject * obj;
1773
1774 CHECK( IORegistryEntry, registry_entry, entry );
1775
1776 obj = entry->copyProperty(property_name);
1777 if( !obj)
1778 return( kIOReturnNotFound );
1779
1780 OSSerialize * s = OSSerialize::withCapacity(4096);
1781 if( !s) {
1782 obj->release();
1783 return( kIOReturnNoMemory );
1784 }
1785 s->clearText();
1786
1787 if( obj->serialize( s )) {
1788 len = s->getLength();
1789 *propertiesCnt = len;
1790 err = copyoutkdata( s->text(), len, properties );
1791
1792 } else
1793 err = kIOReturnUnsupported;
1794
1795 s->release();
1796 obj->release();
1797
1798 return( err );
1799 }
1800
1801 /* Routine io_registry_entry_get_property_recursively */
1802 kern_return_t is_io_registry_entry_get_property_recursively(
1803 io_object_t registry_entry,
1804 io_name_t plane,
1805 io_name_t property_name,
1806 int options,
1807 io_buf_ptr_t *properties,
1808 mach_msg_type_number_t *propertiesCnt )
1809 {
1810 kern_return_t err;
1811 vm_size_t len;
1812 OSObject * obj;
1813
1814 CHECK( IORegistryEntry, registry_entry, entry );
1815
1816 obj = entry->copyProperty( property_name,
1817 IORegistryEntry::getPlane( plane ), options);
1818 if( !obj)
1819 return( kIOReturnNotFound );
1820
1821 OSSerialize * s = OSSerialize::withCapacity(4096);
1822 if( !s) {
1823 obj->release();
1824 return( kIOReturnNoMemory );
1825 }
1826
1827 s->clearText();
1828
1829 if( obj->serialize( s )) {
1830 len = s->getLength();
1831 *propertiesCnt = len;
1832 err = copyoutkdata( s->text(), len, properties );
1833
1834 } else
1835 err = kIOReturnUnsupported;
1836
1837 s->release();
1838 obj->release();
1839
1840 return( err );
1841 }
1842
1843 /* Routine io_registry_entry_get_properties */
1844 kern_return_t is_io_registry_entry_get_properties(
1845 io_object_t registry_entry,
1846 io_buf_ptr_t *properties,
1847 mach_msg_type_number_t *propertiesCnt )
1848 {
1849 kern_return_t err;
1850 vm_size_t len;
1851
1852 CHECK( IORegistryEntry, registry_entry, entry );
1853
1854 OSSerialize * s = OSSerialize::withCapacity(4096);
1855 if( !s)
1856 return( kIOReturnNoMemory );
1857
1858 s->clearText();
1859
1860 if( entry->serializeProperties( s )) {
1861 len = s->getLength();
1862 *propertiesCnt = len;
1863 err = copyoutkdata( s->text(), len, properties );
1864
1865 } else
1866 err = kIOReturnUnsupported;
1867
1868 s->release();
1869
1870 return( err );
1871 }
1872
1873 /* Routine io_registry_entry_set_properties */
1874 kern_return_t is_io_registry_entry_set_properties
1875 (
1876 io_object_t registry_entry,
1877 io_buf_ptr_t properties,
1878 mach_msg_type_number_t propertiesCnt,
1879 natural_t * result)
1880 {
1881 OSObject * obj;
1882 kern_return_t err;
1883 IOReturn res;
1884 vm_offset_t data;
1885 vm_map_offset_t map_data;
1886
1887 CHECK( IORegistryEntry, registry_entry, entry );
1888
1889 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
1890 data = CAST_DOWN(vm_offset_t, map_data);
1891
1892 if( KERN_SUCCESS == err) {
1893
1894 // must return success after vm_map_copyout() succeeds
1895 obj = OSUnserializeXML( (const char *) data );
1896 vm_deallocate( kernel_map, data, propertiesCnt );
1897
1898 if( obj) {
1899 res = entry->setProperties( obj );
1900 obj->release();
1901 } else
1902 res = kIOReturnBadArgument;
1903 } else
1904 res = err;
1905
1906 *result = res;
1907 return( err );
1908 }
1909
1910 /* Routine io_registry_entry_get_child_iterator */
1911 kern_return_t is_io_registry_entry_get_child_iterator(
1912 io_object_t registry_entry,
1913 io_name_t plane,
1914 io_object_t *iterator )
1915 {
1916 CHECK( IORegistryEntry, registry_entry, entry );
1917
1918 *iterator = entry->getChildIterator(
1919 IORegistryEntry::getPlane( plane ));
1920
1921 return( kIOReturnSuccess );
1922 }
1923
1924 /* Routine io_registry_entry_get_parent_iterator */
1925 kern_return_t is_io_registry_entry_get_parent_iterator(
1926 io_object_t registry_entry,
1927 io_name_t plane,
1928 io_object_t *iterator)
1929 {
1930 CHECK( IORegistryEntry, registry_entry, entry );
1931
1932 *iterator = entry->getParentIterator(
1933 IORegistryEntry::getPlane( plane ));
1934
1935 return( kIOReturnSuccess );
1936 }
1937
1938 /* Routine io_service_get_busy_state */
1939 kern_return_t is_io_service_get_busy_state(
1940 io_object_t _service,
1941 int *busyState )
1942 {
1943 CHECK( IOService, _service, service );
1944
1945 *busyState = service->getBusyState();
1946
1947 return( kIOReturnSuccess );
1948 }
1949
1950 /* Routine io_service_get_state */
1951 kern_return_t is_io_service_get_state(
1952 io_object_t _service,
1953 uint64_t *state )
1954 {
1955 CHECK( IOService, _service, service );
1956
1957 *state = service->getState();
1958
1959 return( kIOReturnSuccess );
1960 }
1961
1962 /* Routine io_service_wait_quiet */
1963 kern_return_t is_io_service_wait_quiet(
1964 io_object_t _service,
1965 mach_timespec_t wait_time )
1966 {
1967 CHECK( IOService, _service, service );
1968
1969 return( service->waitQuiet( &wait_time ));
1970 }
1971
1972 /* Routine io_service_request_probe */
1973 kern_return_t is_io_service_request_probe(
1974 io_object_t _service,
1975 int options )
1976 {
1977 CHECK( IOService, _service, service );
1978
1979 return( service->requestProbe( options ));
1980 }
1981
1982
1983 /* Routine io_service_open */
1984 kern_return_t is_io_service_open(
1985 io_object_t _service,
1986 task_t owningTask,
1987 int connect_type,
1988 io_object_t *connection )
1989 {
1990 IOUserClient * client;
1991 IOReturn err;
1992
1993 CHECK( IOService, _service, service );
1994
1995 err = service->newUserClient( owningTask, (void *) owningTask,
1996 connect_type, &client );
1997
1998 if( err == kIOReturnSuccess) {
1999 assert( OSDynamicCast(IOUserClient, client) );
2000 *connection = client;
2001 }
2002
2003 return( err);
2004 }
2005
2006 /* Routine io_service_close */
2007 kern_return_t is_io_service_close(
2008 io_object_t connection )
2009 {
2010 OSSet * mappings;
2011 if ((mappings = OSDynamicCast(OSSet, connection)))
2012 return( kIOReturnSuccess );
2013
2014 CHECK( IOUserClient, connection, client );
2015
2016 client->clientClose();
2017
2018 return( kIOReturnSuccess );
2019 }
2020
2021 /* Routine io_connect_get_service */
2022 kern_return_t is_io_connect_get_service(
2023 io_object_t connection,
2024 io_object_t *service )
2025 {
2026 IOService * theService;
2027
2028 CHECK( IOUserClient, connection, client );
2029
2030 theService = client->getService();
2031 if( theService)
2032 theService->retain();
2033
2034 *service = theService;
2035
2036 return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
2037 }
2038
2039 /* Routine io_connect_set_notification_port */
2040 kern_return_t is_io_connect_set_notification_port(
2041 io_object_t connection,
2042 int notification_type,
2043 mach_port_t port,
2044 int reference)
2045 {
2046 CHECK( IOUserClient, connection, client );
2047
2048 return( client->registerNotificationPort( port, notification_type,
2049 reference ));
2050 }
2051
2052 kern_return_t is_io_connect_map_memory(
2053 io_object_t connect,
2054 int type,
2055 task_t task,
2056 vm_address_t * mapAddr,
2057 vm_size_t * mapSize,
2058 int flags )
2059 {
2060 IOReturn err;
2061 IOMemoryMap * map;
2062
2063 CHECK( IOUserClient, connect, client );
2064
2065 map = client->mapClientMemory( type, task, flags, *mapAddr );
2066
2067 if( map) {
2068 *mapAddr = map->getVirtualAddress();
2069 if( mapSize)
2070 *mapSize = map->getLength();
2071
2072 if( task != current_task()) {
2073 // push a name out to the task owning the map,
2074 // so we can clean up maps
2075 #if IOASSERT
2076 mach_port_name_t name =
2077 #endif
2078 IOMachPort::makeSendRightForTask(
2079 task, map, IKOT_IOKIT_OBJECT );
2080 assert( name );
2081
2082 } else {
2083 // keep it with the user client
2084 IOLockLock( gIOObjectPortLock);
2085 if( 0 == client->mappings)
2086 client->mappings = OSSet::withCapacity(2);
2087 if( client->mappings)
2088 client->mappings->setObject( map);
2089 IOLockUnlock( gIOObjectPortLock);
2090 map->release();
2091 }
2092 err = kIOReturnSuccess;
2093
2094 } else
2095 err = kIOReturnBadArgument;
2096
2097 return( err );
2098 }
2099
2100 IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
2101 {
2102 OSIterator * iter;
2103 IOMemoryMap * map = 0;
2104
2105 IOLockLock(gIOObjectPortLock);
2106
2107 iter = OSCollectionIterator::withCollection(mappings);
2108 if(iter)
2109 {
2110 while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject())))
2111 {
2112 if(mem == map->getMemoryDescriptor())
2113 {
2114 map->retain();
2115 mappings->removeObject(map);
2116 break;
2117 }
2118 }
2119 iter->release();
2120 }
2121
2122 IOLockUnlock(gIOObjectPortLock);
2123
2124 return (map);
2125 }
2126
2127 kern_return_t is_io_connect_unmap_memory(
2128 io_object_t connect,
2129 int type,
2130 task_t task,
2131 vm_address_t mapAddr )
2132 {
2133 IOReturn err;
2134 IOOptionBits options = 0;
2135 IOMemoryDescriptor * memory;
2136 IOMemoryMap * map;
2137
2138 CHECK( IOUserClient, connect, client );
2139
2140 err = client->clientMemoryForType( (UInt32) type, &options, &memory );
2141
2142 if( memory && (kIOReturnSuccess == err)) {
2143
2144 options = (options & ~kIOMapUserOptionsMask)
2145 | kIOMapAnywhere | kIOMapReference;
2146
2147 map = memory->map( task, mapAddr, options );
2148 memory->release();
2149 if( map)
2150 {
2151 IOLockLock( gIOObjectPortLock);
2152 if( client->mappings)
2153 client->mappings->removeObject( map);
2154 IOLockUnlock( gIOObjectPortLock);
2155
2156 mach_port_name_t name = 0;
2157 if (task != current_task())
2158 name = IOMachPort::makeSendRightForTask( task, map, IKOT_IOKIT_OBJECT );
2159 if (name)
2160 {
2161 map->unmap();
2162 err = iokit_mod_send_right( task, name, -2 );
2163 err = kIOReturnSuccess;
2164 }
2165 else
2166 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
2167 if (task == current_task())
2168 map->release();
2169 }
2170 else
2171 err = kIOReturnBadArgument;
2172 }
2173
2174 return( err );
2175 }
2176
2177
2178 /* Routine io_connect_add_client */
2179 kern_return_t is_io_connect_add_client(
2180 io_object_t connection,
2181 io_object_t connect_to)
2182 {
2183 CHECK( IOUserClient, connection, client );
2184 CHECK( IOUserClient, connect_to, to );
2185
2186 return( client->connectClient( to ) );
2187 }
2188
2189
2190 /* Routine io_connect_set_properties */
2191 kern_return_t is_io_connect_set_properties(
2192 io_object_t connection,
2193 io_buf_ptr_t properties,
2194 mach_msg_type_number_t propertiesCnt,
2195 natural_t * result)
2196 {
2197 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
2198 }
2199
2200
2201 /* Routine io_connect_method_scalarI_scalarO */
2202 kern_return_t is_io_connect_method_scalarI_scalarO(
2203 io_object_t connect,
2204 UInt32 index,
2205 void * input[],
2206 IOByteCount inputCount,
2207 void * output[],
2208 IOByteCount * outputCount )
2209 {
2210 IOReturn err;
2211 IOExternalMethod * method;
2212 IOService * object;
2213 IOMethod func;
2214
2215 CHECK( IOUserClient, connect, client);
2216 if( (method = client->getTargetAndMethodForIndex(&object, index))) {
2217 do {
2218 err = kIOReturnBadArgument;
2219 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
2220 continue;
2221 if( inputCount != method->count0)
2222 continue;
2223 if( *outputCount != method->count1)
2224 continue;
2225
2226 func = method->func;
2227
2228 switch( inputCount) {
2229
2230 case 6:
2231 err = (object->*func)( input[0], input[1], input[2],
2232 input[3], input[4], input[5] );
2233 break;
2234 case 5:
2235 err = (object->*func)( input[0], input[1], input[2],
2236 input[3], input[4],
2237 &output[0] );
2238 break;
2239 case 4:
2240 err = (object->*func)( input[0], input[1], input[2],
2241 input[3],
2242 &output[0], &output[1] );
2243 break;
2244 case 3:
2245 err = (object->*func)( input[0], input[1], input[2],
2246 &output[0], &output[1], &output[2] );
2247 break;
2248 case 2:
2249 err = (object->*func)( input[0], input[1],
2250 &output[0], &output[1], &output[2],
2251 &output[3] );
2252 break;
2253 case 1:
2254 err = (object->*func)( input[0],
2255 &output[0], &output[1], &output[2],
2256 &output[3], &output[4] );
2257 break;
2258 case 0:
2259 err = (object->*func)( &output[0], &output[1], &output[2],
2260 &output[3], &output[4], &output[5] );
2261 break;
2262
2263 default:
2264 IOLog("%s: Bad method table\n", client->getName());
2265 }
2266 } while( false);
2267
2268 } else
2269 err = kIOReturnUnsupported;
2270
2271 return( err);
2272 }
2273
2274 /* Routine io_connect_method_scalarI_structureO */
2275 kern_return_t is_io_connect_method_scalarI_structureO(
2276 io_object_t connect,
2277 UInt32 index,
2278 void * input[],
2279 IOByteCount inputCount,
2280 void * output,
2281 IOByteCount * outputCount )
2282 {
2283 IOReturn err;
2284 IOExternalMethod * method;
2285 IOService * object;
2286 IOMethod func;
2287
2288 CHECK( IOUserClient, connect, client);
2289
2290 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2291 do {
2292 err = kIOReturnBadArgument;
2293 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
2294 continue;
2295 if( inputCount != method->count0)
2296 continue;
2297 if( (0xffffffff != method->count1)
2298 && (*outputCount != method->count1))
2299 continue;
2300
2301 func = method->func;
2302
2303 switch( inputCount) {
2304
2305 case 5:
2306 err = (object->*func)( input[0], input[1], input[2],
2307 input[3], input[4],
2308 output );
2309 break;
2310 case 4:
2311 err = (object->*func)( input[0], input[1], input[2],
2312 input[3],
2313 output, (void *)outputCount );
2314 break;
2315 case 3:
2316 err = (object->*func)( input[0], input[1], input[2],
2317 output, (void *)outputCount, 0 );
2318 break;
2319 case 2:
2320 err = (object->*func)( input[0], input[1],
2321 output, (void *)outputCount, 0, 0 );
2322 break;
2323 case 1:
2324 err = (object->*func)( input[0],
2325 output, (void *)outputCount, 0, 0, 0 );
2326 break;
2327 case 0:
2328 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 );
2329 break;
2330
2331 default:
2332 IOLog("%s: Bad method table\n", client->getName());
2333 }
2334 } while( false);
2335
2336 } else
2337 err = kIOReturnUnsupported;
2338
2339 return( err);
2340 }
2341
2342 /* Routine io_connect_method_scalarI_structureI */
2343 kern_return_t is_io_connect_method_scalarI_structureI(
2344 io_connect_t connect,
2345 UInt32 index,
2346 void * input[],
2347 IOByteCount inputCount,
2348 UInt8 * inputStruct,
2349 IOByteCount inputStructCount )
2350 {
2351 IOReturn err;
2352 IOExternalMethod * method;
2353 IOService * object;
2354 IOMethod func;
2355
2356 CHECK( IOUserClient, connect, client);
2357
2358 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2359 do {
2360 err = kIOReturnBadArgument;
2361 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
2362 continue;
2363 if( (0xffffffff != method->count0)
2364 && (inputCount != method->count0))
2365 continue;
2366 if( (0xffffffff != method->count1)
2367 && (inputStructCount != method->count1))
2368 continue;
2369
2370 func = method->func;
2371
2372 switch( inputCount) {
2373
2374 case 5:
2375 err = (object->*func)( input[0], input[1], input[2],
2376 input[3], input[4],
2377 inputStruct );
2378 break;
2379 case 4:
2380 err = (object->*func)( input[0], input[1], input[2],
2381 input[3],
2382 inputStruct, (void *)inputStructCount );
2383 break;
2384 case 3:
2385 err = (object->*func)( input[0], input[1], input[2],
2386 inputStruct, (void *)inputStructCount,
2387 0 );
2388 break;
2389 case 2:
2390 err = (object->*func)( input[0], input[1],
2391 inputStruct, (void *)inputStructCount,
2392 0, 0 );
2393 break;
2394 case 1:
2395 err = (object->*func)( input[0],
2396 inputStruct, (void *)inputStructCount,
2397 0, 0, 0 );
2398 break;
2399 case 0:
2400 err = (object->*func)( inputStruct, (void *)inputStructCount,
2401 0, 0, 0, 0 );
2402 break;
2403
2404 default:
2405 IOLog("%s: Bad method table\n", client->getName());
2406 }
2407 } while( false);
2408
2409 } else
2410 err = kIOReturnUnsupported;
2411
2412 return( err);
2413 }
2414
2415 /* Routine io_connect_method_structureI_structureO */
2416 kern_return_t is_io_connect_method_structureI_structureO(
2417 io_object_t connect,
2418 UInt32 index,
2419 UInt8 * input,
2420 IOByteCount inputCount,
2421 UInt8 * output,
2422 IOByteCount * outputCount )
2423 {
2424 IOReturn err;
2425 IOExternalMethod * method;
2426 IOService * object;
2427 IOMethod func;
2428
2429 CHECK( IOUserClient, connect, client);
2430
2431 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2432 do {
2433 err = kIOReturnBadArgument;
2434 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
2435 continue;
2436 if( (0xffffffff != method->count0)
2437 && (inputCount != method->count0))
2438 continue;
2439 if( (0xffffffff != method->count1)
2440 && (*outputCount != method->count1))
2441 continue;
2442
2443 func = method->func;
2444
2445 if( method->count1) {
2446 if( method->count0) {
2447 err = (object->*func)( input, output,
2448 (void *)inputCount, outputCount, 0, 0 );
2449 } else {
2450 err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
2451 }
2452 } else {
2453 err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
2454 }
2455
2456 } while( false);
2457
2458 } else
2459 err = kIOReturnUnsupported;
2460
2461 return( err);
2462 }
2463
2464 kern_return_t is_io_async_method_scalarI_scalarO(
2465 io_object_t connect,
2466 mach_port_t wakePort,
2467 io_async_ref_t reference,
2468 mach_msg_type_number_t referenceCnt,
2469 UInt32 index,
2470 void * input[],
2471 IOByteCount inputCount,
2472 void * output[],
2473 IOByteCount * outputCount )
2474 {
2475 IOReturn err;
2476 IOExternalAsyncMethod *method;
2477 IOService * object;
2478 IOAsyncMethod func;
2479
2480 CHECK( IOUserClient, connect, client);
2481 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2482 do {
2483 err = kIOReturnBadArgument;
2484 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
2485 continue;
2486 if( inputCount != method->count0)
2487 continue;
2488 if( *outputCount != method->count1)
2489 continue;
2490
2491 reference[0] = (natural_t) wakePort;
2492 func = method->func;
2493
2494 switch( inputCount) {
2495
2496 case 6:
2497 err = (object->*func)( reference,
2498 input[0], input[1], input[2],
2499 input[3], input[4], input[5] );
2500 break;
2501 case 5:
2502 err = (object->*func)( reference,
2503 input[0], input[1], input[2],
2504 input[3], input[4],
2505 &output[0] );
2506 break;
2507 case 4:
2508 err = (object->*func)( reference,
2509 input[0], input[1], input[2],
2510 input[3],
2511 &output[0], &output[1] );
2512 break;
2513 case 3:
2514 err = (object->*func)( reference,
2515 input[0], input[1], input[2],
2516 &output[0], &output[1], &output[2] );
2517 break;
2518 case 2:
2519 err = (object->*func)( reference,
2520 input[0], input[1],
2521 &output[0], &output[1], &output[2],
2522 &output[3] );
2523 break;
2524 case 1:
2525 err = (object->*func)( reference,
2526 input[0],
2527 &output[0], &output[1], &output[2],
2528 &output[3], &output[4] );
2529 break;
2530 case 0:
2531 err = (object->*func)( reference,
2532 &output[0], &output[1], &output[2],
2533 &output[3], &output[4], &output[5] );
2534 break;
2535
2536 default:
2537 IOLog("%s: Bad method table\n", client->getName());
2538 }
2539 } while( false);
2540
2541 } else
2542 err = kIOReturnUnsupported;
2543
2544 return( err);
2545 }
2546
2547 kern_return_t is_io_async_method_scalarI_structureO(
2548 io_object_t connect,
2549 mach_port_t wakePort,
2550 io_async_ref_t reference,
2551 mach_msg_type_number_t referenceCnt,
2552 UInt32 index,
2553 void * input[],
2554 IOByteCount inputCount,
2555 void * output,
2556 IOByteCount * outputCount )
2557 {
2558 IOReturn err;
2559 IOExternalAsyncMethod *method;
2560 IOService * object;
2561 IOAsyncMethod func;
2562
2563 CHECK( IOUserClient, connect, client);
2564
2565 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2566 do {
2567 err = kIOReturnBadArgument;
2568 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
2569 continue;
2570 if( inputCount != method->count0)
2571 continue;
2572 if( (0xffffffff != method->count1)
2573 && (*outputCount != method->count1))
2574 continue;
2575
2576 reference[0] = (natural_t) wakePort;
2577 func = method->func;
2578
2579 switch( inputCount) {
2580
2581 case 5:
2582 err = (object->*func)( reference,
2583 input[0], input[1], input[2],
2584 input[3], input[4],
2585 output );
2586 break;
2587 case 4:
2588 err = (object->*func)( reference,
2589 input[0], input[1], input[2],
2590 input[3],
2591 output, (void *)outputCount );
2592 break;
2593 case 3:
2594 err = (object->*func)( reference,
2595 input[0], input[1], input[2],
2596 output, (void *)outputCount, 0 );
2597 break;
2598 case 2:
2599 err = (object->*func)( reference,
2600 input[0], input[1],
2601 output, (void *)outputCount, 0, 0 );
2602 break;
2603 case 1:
2604 err = (object->*func)( reference,
2605 input[0],
2606 output, (void *)outputCount, 0, 0, 0 );
2607 break;
2608 case 0:
2609 err = (object->*func)( reference,
2610 output, (void *)outputCount, 0, 0, 0, 0 );
2611 break;
2612
2613 default:
2614 IOLog("%s: Bad method table\n", client->getName());
2615 }
2616 } while( false);
2617
2618 } else
2619 err = kIOReturnUnsupported;
2620
2621 return( err);
2622 }
2623
2624 kern_return_t is_io_async_method_scalarI_structureI(
2625 io_connect_t connect,
2626 mach_port_t wakePort,
2627 io_async_ref_t reference,
2628 mach_msg_type_number_t referenceCnt,
2629 UInt32 index,
2630 void * input[],
2631 IOByteCount inputCount,
2632 UInt8 * inputStruct,
2633 IOByteCount inputStructCount )
2634 {
2635 IOReturn err;
2636 IOExternalAsyncMethod *method;
2637 IOService * object;
2638 IOAsyncMethod func;
2639
2640 CHECK( IOUserClient, connect, client);
2641
2642 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2643 do {
2644 err = kIOReturnBadArgument;
2645 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
2646 continue;
2647 if( (0xffffffff != method->count0)
2648 && (inputCount != method->count0))
2649 continue;
2650 if( (0xffffffff != method->count1)
2651 && (inputStructCount != method->count1))
2652 continue;
2653
2654 reference[0] = (natural_t) wakePort;
2655 func = method->func;
2656
2657 switch( inputCount) {
2658
2659 case 5:
2660 err = (object->*func)( reference,
2661 input[0], input[1], input[2],
2662 input[3], input[4],
2663 inputStruct );
2664 break;
2665 case 4:
2666 err = (object->*func)( reference,
2667 input[0], input[1], input[2],
2668 input[3],
2669 inputStruct, (void *)inputStructCount );
2670 break;
2671 case 3:
2672 err = (object->*func)( reference,
2673 input[0], input[1], input[2],
2674 inputStruct, (void *)inputStructCount,
2675 0 );
2676 break;
2677 case 2:
2678 err = (object->*func)( reference,
2679 input[0], input[1],
2680 inputStruct, (void *)inputStructCount,
2681 0, 0 );
2682 break;
2683 case 1:
2684 err = (object->*func)( reference,
2685 input[0],
2686 inputStruct, (void *)inputStructCount,
2687 0, 0, 0 );
2688 break;
2689 case 0:
2690 err = (object->*func)( reference,
2691 inputStruct, (void *)inputStructCount,
2692 0, 0, 0, 0 );
2693 break;
2694
2695 default:
2696 IOLog("%s: Bad method table\n", client->getName());
2697 }
2698 } while( false);
2699
2700 } else
2701 err = kIOReturnUnsupported;
2702
2703 return( err);
2704 }
2705
2706 kern_return_t is_io_async_method_structureI_structureO(
2707 io_object_t connect,
2708 mach_port_t wakePort,
2709 io_async_ref_t reference,
2710 mach_msg_type_number_t referenceCnt,
2711 UInt32 index,
2712 UInt8 * input,
2713 IOByteCount inputCount,
2714 UInt8 * output,
2715 IOByteCount * outputCount )
2716 {
2717 IOReturn err;
2718 IOExternalAsyncMethod *method;
2719 IOService * object;
2720 IOAsyncMethod func;
2721
2722 CHECK( IOUserClient, connect, client);
2723
2724 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2725 do {
2726 err = kIOReturnBadArgument;
2727 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
2728 continue;
2729 if( (0xffffffff != method->count0)
2730 && (inputCount != method->count0))
2731 continue;
2732 if( (0xffffffff != method->count1)
2733 && (*outputCount != method->count1))
2734 continue;
2735
2736 reference[0] = (natural_t) wakePort;
2737 func = method->func;
2738
2739 if( method->count1) {
2740 if( method->count0) {
2741 err = (object->*func)( reference,
2742 input, output,
2743 (void *)inputCount, outputCount, 0, 0 );
2744 } else {
2745 err = (object->*func)( reference,
2746 output, outputCount, 0, 0, 0, 0 );
2747 }
2748 } else {
2749 err = (object->*func)( reference,
2750 input, (void *)inputCount, 0, 0, 0, 0 );
2751 }
2752
2753 } while( false);
2754
2755 } else
2756 err = kIOReturnUnsupported;
2757
2758 return( err);
2759 }
2760 /* Routine io_make_matching */
2761 kern_return_t is_io_make_matching(
2762 mach_port_t master_port,
2763 UInt32 type,
2764 IOOptionBits options,
2765 UInt8 * input,
2766 IOByteCount inputCount,
2767 io_string_t matching )
2768 {
2769 OSSerialize * s;
2770 IOReturn err = kIOReturnSuccess;
2771 OSDictionary * dict;
2772
2773 if( master_port != master_device_port)
2774 return( kIOReturnNotPrivileged);
2775
2776 switch( type) {
2777
2778 case kIOServiceMatching:
2779 dict = IOService::serviceMatching( gIOServiceKey );
2780 break;
2781
2782 case kIOBSDNameMatching:
2783 dict = IOBSDNameMatching( (const char *) input );
2784 break;
2785
2786 case kIOOFPathMatching:
2787 dict = IOOFPathMatching( (const char *) input,
2788 matching, sizeof( io_string_t));
2789 break;
2790
2791 default:
2792 dict = 0;
2793 }
2794
2795 if( !dict)
2796 return( kIOReturnUnsupported);
2797
2798 do {
2799 s = OSSerialize::withCapacity(4096);
2800 if( !s) {
2801 err = kIOReturnNoMemory;
2802 continue;
2803 }
2804 s->clearText();
2805 if( !dict->serialize( s )) {
2806 err = kIOReturnUnsupported;
2807 continue;
2808 }
2809
2810 if( s->getLength() > sizeof( io_string_t)) {
2811 err = kIOReturnNoMemory;
2812 continue;
2813 } else
2814 strcpy( matching, s->text());
2815
2816 } while( false);
2817
2818 if( s)
2819 s->release();
2820 if( dict)
2821 dict->release();
2822
2823 return( err);
2824 }
2825
2826 /* Routine io_catalog_send_data */
2827 kern_return_t is_io_catalog_send_data(
2828 mach_port_t master_port,
2829 int flag,
2830 io_buf_ptr_t inData,
2831 mach_msg_type_number_t inDataCount,
2832 natural_t * result)
2833 {
2834 OSObject * obj = 0;
2835 vm_offset_t data;
2836 kern_return_t kr = kIOReturnError;
2837
2838 //printf("io_catalog_send_data called. flag: %d\n", flag);
2839
2840 if( master_port != master_device_port)
2841 return kIOReturnNotPrivileged;
2842
2843 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2844 if(flag != kIOCatalogRemoveKernelLinker && ( !inData || !inDataCount) )
2845 return kIOReturnBadArgument;
2846
2847 if (inData) {
2848 vm_map_offset_t map_data;
2849
2850 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
2851 data = CAST_DOWN(vm_offset_t, map_data);
2852
2853 if( kr != KERN_SUCCESS)
2854 return kr;
2855
2856 // must return success after vm_map_copyout() succeeds
2857
2858 if( inDataCount ) {
2859 obj = (OSObject *)OSUnserializeXML((const char *)data);
2860 vm_deallocate( kernel_map, data, inDataCount );
2861 if( !obj) {
2862 *result = kIOReturnNoMemory;
2863 return( KERN_SUCCESS);
2864 }
2865 }
2866 }
2867
2868 switch ( flag ) {
2869 case kIOCatalogAddDrivers:
2870 case kIOCatalogAddDriversNoMatch: {
2871 OSArray * array;
2872
2873 array = OSDynamicCast(OSArray, obj);
2874 if ( array ) {
2875 if ( !gIOCatalogue->addDrivers( array ,
2876 flag == kIOCatalogAddDrivers) ) {
2877 kr = kIOReturnError;
2878 }
2879 }
2880 else {
2881 kr = kIOReturnBadArgument;
2882 }
2883 }
2884 break;
2885
2886 case kIOCatalogRemoveDrivers:
2887 case kIOCatalogRemoveDriversNoMatch: {
2888 OSDictionary * dict;
2889
2890 dict = OSDynamicCast(OSDictionary, obj);
2891 if ( dict ) {
2892 if ( !gIOCatalogue->removeDrivers( dict,
2893 flag == kIOCatalogRemoveDrivers ) ) {
2894 kr = kIOReturnError;
2895 }
2896 }
2897 else {
2898 kr = kIOReturnBadArgument;
2899 }
2900 }
2901 break;
2902
2903 case kIOCatalogStartMatching: {
2904 OSDictionary * dict;
2905
2906 dict = OSDynamicCast(OSDictionary, obj);
2907 if ( dict ) {
2908 if ( !gIOCatalogue->startMatching( dict ) ) {
2909 kr = kIOReturnError;
2910 }
2911 }
2912 else {
2913 kr = kIOReturnBadArgument;
2914 }
2915 }
2916 break;
2917
2918 case kIOCatalogRemoveKernelLinker: {
2919 if (gIOCatalogue->removeKernelLinker() != KERN_SUCCESS) {
2920 kr = kIOReturnError;
2921 } else {
2922 kr = kIOReturnSuccess;
2923 }
2924 }
2925 break;
2926
2927 default:
2928 kr = kIOReturnBadArgument;
2929 break;
2930 }
2931
2932 if (obj) obj->release();
2933
2934 *result = kr;
2935 return( KERN_SUCCESS);
2936 }
2937
2938 /* Routine io_catalog_terminate */
2939 kern_return_t is_io_catalog_terminate(
2940 mach_port_t master_port,
2941 int flag,
2942 io_name_t name )
2943 {
2944 kern_return_t kr;
2945
2946 if( master_port != master_device_port )
2947 return kIOReturnNotPrivileged;
2948
2949 kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
2950 kIOClientPrivilegeAdministrator );
2951 if( kIOReturnSuccess != kr)
2952 return( kr );
2953
2954 switch ( flag ) {
2955 case kIOCatalogServiceTerminate:
2956 OSIterator * iter;
2957 IOService * service;
2958
2959 iter = IORegistryIterator::iterateOver(gIOServicePlane,
2960 kIORegistryIterateRecursively);
2961 if ( !iter )
2962 return kIOReturnNoMemory;
2963
2964 do {
2965 iter->reset();
2966 while( (service = (IOService *)iter->getNextObject()) ) {
2967 if( service->metaCast(name)) {
2968 if ( !service->terminate( kIOServiceRequired
2969 | kIOServiceSynchronous) ) {
2970 kr = kIOReturnUnsupported;
2971 break;
2972 }
2973 }
2974 }
2975 } while( !service && !iter->isValid());
2976 iter->release();
2977 break;
2978
2979 case kIOCatalogModuleUnload:
2980 case kIOCatalogModuleTerminate:
2981 kr = gIOCatalogue->terminateDriversForModule(name,
2982 flag == kIOCatalogModuleUnload);
2983 break;
2984
2985 default:
2986 kr = kIOReturnBadArgument;
2987 break;
2988 }
2989
2990 return( kr );
2991 }
2992
2993 /* Routine io_catalog_get_data */
2994 kern_return_t is_io_catalog_get_data(
2995 mach_port_t master_port,
2996 int flag,
2997 io_buf_ptr_t *outData,
2998 mach_msg_type_number_t *outDataCount)
2999 {
3000 kern_return_t kr = kIOReturnSuccess;
3001 OSSerialize * s;
3002
3003 if( master_port != master_device_port)
3004 return kIOReturnNotPrivileged;
3005
3006 //printf("io_catalog_get_data called. flag: %d\n", flag);
3007
3008 s = OSSerialize::withCapacity(4096);
3009 if ( !s )
3010 return kIOReturnNoMemory;
3011
3012 s->clearText();
3013
3014 kr = gIOCatalogue->serializeData(flag, s);
3015
3016 if ( kr == kIOReturnSuccess ) {
3017 vm_offset_t data;
3018 vm_map_copy_t copy;
3019 vm_size_t size;
3020
3021 size = s->getLength();
3022 kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
3023 if ( kr == kIOReturnSuccess ) {
3024 bcopy(s->text(), (void *)data, size);
3025 kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
3026 (vm_map_size_t)size, true, &copy);
3027 *outData = (char *)copy;
3028 *outDataCount = size;
3029 }
3030 }
3031
3032 s->release();
3033
3034 return kr;
3035 }
3036
3037 /* Routine io_catalog_get_gen_count */
3038 kern_return_t is_io_catalog_get_gen_count(
3039 mach_port_t master_port,
3040 int *genCount)
3041 {
3042 if( master_port != master_device_port)
3043 return kIOReturnNotPrivileged;
3044
3045 //printf("io_catalog_get_gen_count called.\n");
3046
3047 if ( !genCount )
3048 return kIOReturnBadArgument;
3049
3050 *genCount = gIOCatalogue->getGenerationCount();
3051
3052 return kIOReturnSuccess;
3053 }
3054
3055 /* Routine io_catalog_module_loaded */
3056 kern_return_t is_io_catalog_module_loaded(
3057 mach_port_t master_port,
3058 io_name_t name)
3059 {
3060 if( master_port != master_device_port)
3061 return kIOReturnNotPrivileged;
3062
3063 //printf("io_catalog_module_loaded called. name %s\n", name);
3064
3065 if ( !name )
3066 return kIOReturnBadArgument;
3067
3068 gIOCatalogue->moduleHasLoaded(name);
3069
3070 return kIOReturnSuccess;
3071 }
3072
3073 kern_return_t is_io_catalog_reset(
3074 mach_port_t master_port,
3075 int flag)
3076 {
3077 if( master_port != master_device_port)
3078 return kIOReturnNotPrivileged;
3079
3080 switch ( flag ) {
3081 case kIOCatalogResetDefault:
3082 gIOCatalogue->reset();
3083 break;
3084
3085 default:
3086 return kIOReturnBadArgument;
3087 }
3088
3089 return kIOReturnSuccess;
3090 }
3091
3092 kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
3093 {
3094 kern_return_t result = kIOReturnBadArgument;
3095 IOUserClient *userClient;
3096
3097 if ((userClient = OSDynamicCast(IOUserClient,
3098 iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
3099 IOExternalTrap *trap;
3100 IOService *target = NULL;
3101
3102 trap = userClient->getTargetAndTrapForIndex(&target, args->index);
3103
3104 if (trap && target) {
3105 IOTrap func;
3106
3107 func = trap->func;
3108
3109 if (func) {
3110 result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
3111 }
3112 }
3113
3114 userClient->release();
3115 }
3116
3117 return result;
3118 }
3119
3120 }; /* extern "C" */
3121
3122 OSMetaClassDefineReservedUnused(IOUserClient, 0);
3123 OSMetaClassDefineReservedUnused(IOUserClient, 1);
3124 OSMetaClassDefineReservedUnused(IOUserClient, 2);
3125 OSMetaClassDefineReservedUnused(IOUserClient, 3);
3126 OSMetaClassDefineReservedUnused(IOUserClient, 4);
3127 OSMetaClassDefineReservedUnused(IOUserClient, 5);
3128 OSMetaClassDefineReservedUnused(IOUserClient, 6);
3129 OSMetaClassDefineReservedUnused(IOUserClient, 7);
3130 OSMetaClassDefineReservedUnused(IOUserClient, 8);
3131 OSMetaClassDefineReservedUnused(IOUserClient, 9);
3132 OSMetaClassDefineReservedUnused(IOUserClient, 10);
3133 OSMetaClassDefineReservedUnused(IOUserClient, 11);
3134 OSMetaClassDefineReservedUnused(IOUserClient, 12);
3135 OSMetaClassDefineReservedUnused(IOUserClient, 13);
3136 OSMetaClassDefineReservedUnused(IOUserClient, 14);
3137 OSMetaClassDefineReservedUnused(IOUserClient, 15);
3138