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