]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOUserClient.cpp
5168fdce3c2a625f358150bc9ff37d9a5b78465e
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
1 /*
2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31
32 #include <IOKit/IOKitServer.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IORegistryEntry.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOMemoryDescriptor.h>
38 #include <IOKit/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 IOReturn IOUserClient::clientHasPrivilege( void * securityToken,
768 const char * privilegeName )
769 {
770 kern_return_t kr;
771 security_token_t token;
772 mach_msg_type_number_t count;
773
774 count = TASK_SECURITY_TOKEN_COUNT;
775 kr = task_info( (task_t) securityToken, TASK_SECURITY_TOKEN,
776 (task_info_t) &token, &count );
777
778 if (KERN_SUCCESS != kr)
779 {}
780 else if (!strcmp(privilegeName, kIOClientPrivilegeAdministrator))
781 {
782 if (0 != token.val[0])
783 kr = kIOReturnNotPrivileged;
784 }
785 else if (!strcmp(privilegeName, kIOClientPrivilegeLocalUser))
786 {
787 OSArray * array;
788 OSDictionary * user = 0;
789
790 if ((array = OSDynamicCast(OSArray,
791 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
792 {
793 for (unsigned int idx = 0;
794 (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
795 idx++)
796 {
797 OSNumber * num;
798 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
799 && (token.val[0] == num->unsigned32BitValue()))
800 break;
801 }
802 array->release();
803 }
804 if (!user)
805 kr = kIOReturnNotPrivileged;
806 }
807 else
808 kr = kIOReturnUnsupported;
809
810 return (kr);
811 }
812
813 bool IOUserClient::init()
814 {
815 if( getPropertyTable())
816 return true;
817 else
818 return super::init();
819 }
820
821 bool IOUserClient::init(OSDictionary * dictionary)
822 {
823 if( getPropertyTable())
824 return true;
825 else
826 return super::init(dictionary);
827 }
828
829 bool IOUserClient::initWithTask(task_t owningTask,
830 void * securityID,
831 UInt32 type )
832 {
833 if( getPropertyTable())
834 return true;
835 else
836 return super::init();
837 }
838
839 bool IOUserClient::initWithTask(task_t owningTask,
840 void * securityID,
841 UInt32 type,
842 OSDictionary * properties )
843 {
844 bool ok;
845
846 ok = super::init( properties );
847 ok &= initWithTask( owningTask, securityID, type );
848
849 return( ok );
850 }
851
852 void IOUserClient::free()
853 {
854 if( mappings)
855 mappings->release();
856
857 super::free();
858 }
859
860 IOReturn IOUserClient::clientDied( void )
861 {
862 return( clientClose());
863 }
864
865 IOReturn IOUserClient::clientClose( void )
866 {
867 return( kIOReturnUnsupported );
868 }
869
870 IOService * IOUserClient::getService( void )
871 {
872 return( 0 );
873 }
874
875 IOReturn IOUserClient::registerNotificationPort(
876 mach_port_t /* port */,
877 UInt32 /* type */,
878 UInt32 /* refCon */)
879 {
880 return( kIOReturnUnsupported);
881 }
882
883 IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
884 semaphore_t * semaphore )
885 {
886 return( kIOReturnUnsupported);
887 }
888
889 IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
890 {
891 return( kIOReturnUnsupported);
892 }
893
894 IOReturn IOUserClient::clientMemoryForType( UInt32 type,
895 IOOptionBits * options,
896 IOMemoryDescriptor ** memory )
897 {
898 return( kIOReturnUnsupported);
899 }
900
901 IOMemoryMap * IOUserClient::mapClientMemory(
902 IOOptionBits type,
903 task_t task,
904 IOOptionBits mapFlags,
905 IOVirtualAddress atAddress )
906 {
907 IOReturn err;
908 IOOptionBits options = 0;
909 IOMemoryDescriptor * memory;
910 IOMemoryMap * map = 0;
911
912 err = clientMemoryForType( (UInt32) type, &options, &memory );
913
914 if( memory && (kIOReturnSuccess == err)) {
915
916 options = (options & ~kIOMapUserOptionsMask)
917 | (mapFlags & kIOMapUserOptionsMask);
918 map = memory->map( task, atAddress, options );
919 memory->release();
920 }
921
922 return( map );
923 }
924
925 IOReturn IOUserClient::exportObjectToClient(task_t task,
926 OSObject *obj, io_object_t *clientObj)
927 {
928 mach_port_name_t name;
929
930 name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
931 assert( name );
932
933 *(mach_port_name_t *)clientObj = name;
934 return kIOReturnSuccess;
935 }
936
937 IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
938 {
939 return( 0 );
940 }
941
942 IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
943 {
944 return( 0 );
945 }
946
947 IOExternalMethod * IOUserClient::
948 getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
949 {
950 IOExternalMethod *method = getExternalMethodForIndex(index);
951
952 if (method)
953 *targetP = (IOService *) method->object;
954
955 return method;
956 }
957
958 IOExternalAsyncMethod * IOUserClient::
959 getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
960 {
961 IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
962
963 if (method)
964 *targetP = (IOService *) method->object;
965
966 return method;
967 }
968
969 IOExternalTrap * IOUserClient::
970 getExternalTrapForIndex(UInt32 index)
971 {
972 return NULL;
973 }
974
975 IOExternalTrap * IOUserClient::
976 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
977 {
978 IOExternalTrap *trap = getExternalTrapForIndex(index);
979
980 if (trap) {
981 *targetP = trap->object;
982 }
983
984 return trap;
985 }
986
987 IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
988 IOReturn result, void *args[], UInt32 numArgs)
989 {
990 struct ReplyMsg {
991 mach_msg_header_t msgHdr;
992 OSNotificationHeader notifyHdr;
993 IOAsyncCompletionContent asyncContent;
994 void * args[kMaxAsyncArgs];
995 };
996 ReplyMsg replyMsg;
997 mach_port_t replyPort;
998 kern_return_t kr;
999
1000 // If no reply port, do nothing.
1001 replyPort = (mach_port_t) reference[0];
1002 if(replyPort == MACH_PORT_NULL)
1003 return kIOReturnSuccess;
1004
1005 if(numArgs > kMaxAsyncArgs)
1006 return kIOReturnMessageTooLarge;
1007 replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
1008 0 /*local*/);
1009 replyMsg.msgHdr.msgh_size =
1010 sizeof(replyMsg) - (kMaxAsyncArgs-numArgs)*sizeof(void *);
1011 replyMsg.msgHdr.msgh_remote_port = replyPort;
1012 replyMsg.msgHdr.msgh_local_port = 0;
1013 replyMsg.msgHdr.msgh_id = kOSNotificationMessageID;
1014
1015 replyMsg.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1016 + numArgs*sizeof(void *);
1017 replyMsg.notifyHdr.type = kIOAsyncCompletionNotificationType;
1018 bcopy( reference, replyMsg.notifyHdr.reference, sizeof(OSAsyncReference));
1019
1020 replyMsg.asyncContent.result = result;
1021 if(numArgs > 0)
1022 bcopy(args, replyMsg.args, sizeof(void *)*numArgs);
1023 kr = mach_msg_send_from_kernel( &replyMsg.msgHdr,
1024 replyMsg.msgHdr.msgh_size);
1025 if( KERN_SUCCESS != kr)
1026 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
1027 return kr;
1028 }
1029
1030 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1031
1032 extern "C" {
1033
1034 #define CHECK(cls,obj,out) \
1035 cls * out; \
1036 if( !(out = OSDynamicCast( cls, obj))) \
1037 return( kIOReturnBadArgument )
1038
1039 /* Routine io_object_get_class */
1040 kern_return_t is_io_object_get_class(
1041 io_object_t object,
1042 io_name_t className )
1043 {
1044 const OSMetaClass* my_obj = NULL;
1045
1046 if( !object)
1047 return( kIOReturnBadArgument );
1048
1049 my_obj = object->getMetaClass();
1050 if (!my_obj) {
1051 return (kIOReturnNotFound);
1052 }
1053
1054 strcpy( className, my_obj->getClassName());
1055 return( kIOReturnSuccess );
1056 }
1057
1058 /* Routine io_object_get_superclass */
1059 kern_return_t is_io_object_get_superclass(
1060 mach_port_t master_port,
1061 io_name_t obj_name,
1062 io_name_t class_name)
1063 {
1064 const OSMetaClass* my_obj = NULL;
1065 const OSMetaClass* superclass = NULL;
1066 const OSSymbol *my_name = NULL;
1067 const char *my_cstr = NULL;
1068
1069 if (!obj_name || !class_name)
1070 return (kIOReturnBadArgument);
1071
1072 if( master_port != master_device_port)
1073 return( kIOReturnNotPrivileged);
1074
1075 my_name = OSSymbol::withCString(obj_name);
1076
1077 if (my_name) {
1078 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1079 my_name->release();
1080 }
1081 if (my_obj) {
1082 superclass = my_obj->getSuperClass();
1083 }
1084
1085 if (!superclass) {
1086 return( kIOReturnNotFound );
1087 }
1088
1089 my_cstr = superclass->getClassName();
1090
1091 if (my_cstr) {
1092 strncpy(class_name, my_cstr, sizeof(io_name_t)-1);
1093 return( kIOReturnSuccess );
1094 }
1095 return (kIOReturnNotFound);
1096 }
1097
1098 /* Routine io_object_get_bundle_identifier */
1099 kern_return_t is_io_object_get_bundle_identifier(
1100 mach_port_t master_port,
1101 io_name_t obj_name,
1102 io_name_t bundle_name)
1103 {
1104 const OSMetaClass* my_obj = NULL;
1105 const OSSymbol *my_name = NULL;
1106 const OSSymbol *identifier = NULL;
1107 const char *my_cstr = NULL;
1108
1109 if (!obj_name || !bundle_name)
1110 return (kIOReturnBadArgument);
1111
1112 if( master_port != master_device_port)
1113 return( kIOReturnNotPrivileged);
1114
1115 my_name = OSSymbol::withCString(obj_name);
1116
1117 if (my_name) {
1118 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1119 my_name->release();
1120 }
1121
1122 if (my_obj) {
1123 identifier = my_obj->getKmodName();
1124 }
1125 if (!identifier) {
1126 return( kIOReturnNotFound );
1127 }
1128
1129 my_cstr = identifier->getCStringNoCopy();
1130 if (my_cstr) {
1131 strncpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t)-1);
1132 return( kIOReturnSuccess );
1133 }
1134
1135 return (kIOReturnBadArgument);
1136 }
1137
1138 /* Routine io_object_conforms_to */
1139 kern_return_t is_io_object_conforms_to(
1140 io_object_t object,
1141 io_name_t className,
1142 boolean_t *conforms )
1143 {
1144 if( !object)
1145 return( kIOReturnBadArgument );
1146
1147 *conforms = (0 != object->metaCast( className ));
1148 return( kIOReturnSuccess );
1149 }
1150
1151 /* Routine io_object_get_retain_count */
1152 kern_return_t is_io_object_get_retain_count(
1153 io_object_t object,
1154 int *retainCount )
1155 {
1156 if( !object)
1157 return( kIOReturnBadArgument );
1158
1159 *retainCount = object->getRetainCount();
1160 return( kIOReturnSuccess );
1161 }
1162
1163 /* Routine io_iterator_next */
1164 kern_return_t is_io_iterator_next(
1165 io_object_t iterator,
1166 io_object_t *object )
1167 {
1168 OSObject * obj;
1169
1170 CHECK( OSIterator, iterator, iter );
1171
1172 obj = iter->getNextObject();
1173 if( obj) {
1174 obj->retain();
1175 *object = obj;
1176 return( kIOReturnSuccess );
1177 } else
1178 return( kIOReturnNoDevice );
1179 }
1180
1181 /* Routine io_iterator_reset */
1182 kern_return_t is_io_iterator_reset(
1183 io_object_t iterator )
1184 {
1185 CHECK( OSIterator, iterator, iter );
1186
1187 iter->reset();
1188
1189 return( kIOReturnSuccess );
1190 }
1191
1192 /* Routine io_iterator_is_valid */
1193 kern_return_t is_io_iterator_is_valid(
1194 io_object_t iterator,
1195 boolean_t *is_valid )
1196 {
1197 CHECK( OSIterator, iterator, iter );
1198
1199 *is_valid = iter->isValid();
1200
1201 return( kIOReturnSuccess );
1202 }
1203
1204 /* Routine io_service_match_property_table */
1205 kern_return_t is_io_service_match_property_table(
1206 io_service_t _service,
1207 io_string_t matching,
1208 boolean_t *matches )
1209 {
1210 CHECK( IOService, _service, service );
1211
1212 kern_return_t kr;
1213 OSObject * obj;
1214 OSDictionary * dict;
1215
1216 obj = OSUnserializeXML( matching );
1217
1218 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1219 *matches = service->passiveMatch( dict );
1220 kr = kIOReturnSuccess;
1221 } else
1222 kr = kIOReturnBadArgument;
1223
1224 if( obj)
1225 obj->release();
1226
1227 return( kr );
1228 }
1229
1230 /* Routine io_service_match_property_table_ool */
1231 kern_return_t is_io_service_match_property_table_ool(
1232 io_object_t service,
1233 io_buf_ptr_t matching,
1234 mach_msg_type_number_t matchingCnt,
1235 natural_t *result,
1236 boolean_t *matches )
1237 {
1238 kern_return_t kr;
1239 vm_offset_t data;
1240 vm_map_offset_t map_data;
1241
1242 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1243 data = CAST_DOWN(vm_offset_t, map_data);
1244
1245 if( KERN_SUCCESS == kr) {
1246 // must return success after vm_map_copyout() succeeds
1247 *result = is_io_service_match_property_table( service,
1248 (char *) data, matches );
1249 vm_deallocate( kernel_map, data, matchingCnt );
1250 }
1251
1252 return( kr );
1253 }
1254
1255 /* Routine io_service_get_matching_services */
1256 kern_return_t is_io_service_get_matching_services(
1257 mach_port_t master_port,
1258 io_string_t matching,
1259 io_iterator_t *existing )
1260 {
1261 kern_return_t kr;
1262 OSObject * obj;
1263 OSDictionary * dict;
1264
1265 if( master_port != master_device_port)
1266 return( kIOReturnNotPrivileged);
1267
1268 obj = OSUnserializeXML( matching );
1269
1270 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1271 *existing = IOService::getMatchingServices( dict );
1272 kr = kIOReturnSuccess;
1273 } else
1274 kr = kIOReturnBadArgument;
1275
1276 if( obj)
1277 obj->release();
1278
1279 return( kr );
1280 }
1281
1282 /* Routine io_service_get_matching_services_ool */
1283 kern_return_t is_io_service_get_matching_services_ool(
1284 mach_port_t master_port,
1285 io_buf_ptr_t matching,
1286 mach_msg_type_number_t matchingCnt,
1287 natural_t *result,
1288 io_object_t *existing )
1289 {
1290 kern_return_t kr;
1291 vm_offset_t data;
1292 vm_map_offset_t map_data;
1293
1294 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1295 data = CAST_DOWN(vm_offset_t, map_data);
1296
1297 if( KERN_SUCCESS == kr) {
1298 // must return success after vm_map_copyout() succeeds
1299 *result = is_io_service_get_matching_services( master_port,
1300 (char *) data, existing );
1301 vm_deallocate( kernel_map, data, matchingCnt );
1302 }
1303
1304 return( kr );
1305 }
1306
1307 /* Routine io_service_add_notification */
1308 kern_return_t is_io_service_add_notification(
1309 mach_port_t master_port,
1310 io_name_t notification_type,
1311 io_string_t matching,
1312 mach_port_t port,
1313 io_async_ref_t reference,
1314 mach_msg_type_number_t referenceCnt,
1315 io_object_t * notification )
1316 {
1317 IOServiceUserNotification * userNotify = 0;
1318 IONotifier * notify = 0;
1319 const OSSymbol * sym;
1320 OSDictionary * dict;
1321 IOReturn err;
1322 unsigned long int userMsgType;
1323
1324
1325 if( master_port != master_device_port)
1326 return( kIOReturnNotPrivileged);
1327
1328 do {
1329 err = kIOReturnNoResources;
1330
1331 if( !(sym = OSSymbol::withCString( notification_type )))
1332 err = kIOReturnNoResources;
1333
1334 if( !(dict = OSDynamicCast( OSDictionary,
1335 OSUnserializeXML( matching )))) {
1336 err = kIOReturnBadArgument;
1337 continue;
1338 }
1339
1340 if( (sym == gIOPublishNotification)
1341 || (sym == gIOFirstPublishNotification))
1342 userMsgType = kIOServicePublishNotificationType;
1343 else if( (sym == gIOMatchedNotification)
1344 || (sym == gIOFirstMatchNotification))
1345 userMsgType = kIOServiceMatchedNotificationType;
1346 else if( sym == gIOTerminatedNotification)
1347 userMsgType = kIOServiceTerminatedNotificationType;
1348 else
1349 userMsgType = kLastIOKitNotificationType;
1350
1351 userNotify = new IOServiceUserNotification;
1352
1353 if( userNotify && !userNotify->init( port, userMsgType,
1354 reference)) {
1355 userNotify->release();
1356 userNotify = 0;
1357 }
1358 if( !userNotify)
1359 continue;
1360
1361 notify = IOService::addNotification( sym, dict,
1362 &userNotify->_handler, userNotify );
1363 if( notify) {
1364 dict = 0;
1365 *notification = userNotify;
1366 userNotify->setNotification( notify );
1367 err = kIOReturnSuccess;
1368 } else
1369 err = kIOReturnUnsupported;
1370
1371 } while( false );
1372
1373 if( sym)
1374 sym->release();
1375 if( dict)
1376 dict->release();
1377
1378 return( err );
1379 }
1380
1381 /* Routine io_service_add_notification_ool */
1382 kern_return_t is_io_service_add_notification_ool(
1383 mach_port_t master_port,
1384 io_name_t notification_type,
1385 io_buf_ptr_t matching,
1386 mach_msg_type_number_t matchingCnt,
1387 mach_port_t wake_port,
1388 io_async_ref_t reference,
1389 mach_msg_type_number_t referenceCnt,
1390 natural_t *result,
1391 io_object_t *notification )
1392 {
1393 kern_return_t kr;
1394 vm_offset_t data;
1395 vm_map_offset_t map_data;
1396
1397 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1398 data = CAST_DOWN(vm_offset_t, map_data);
1399
1400 if( KERN_SUCCESS == kr) {
1401 // must return success after vm_map_copyout() succeeds
1402 *result = is_io_service_add_notification( master_port, notification_type,
1403 (char *) data, wake_port, reference, referenceCnt, notification );
1404 vm_deallocate( kernel_map, data, matchingCnt );
1405 }
1406
1407 return( kr );
1408 }
1409
1410
1411 /* Routine io_service_add_notification_old */
1412 kern_return_t is_io_service_add_notification_old(
1413 mach_port_t master_port,
1414 io_name_t notification_type,
1415 io_string_t matching,
1416 mach_port_t port,
1417 natural_t ref,
1418 io_object_t * notification )
1419 {
1420 return( is_io_service_add_notification( master_port, notification_type,
1421 matching, port, &ref, 1, notification ));
1422 }
1423
1424 /* Routine io_service_add_message_notification */
1425 kern_return_t is_io_service_add_interest_notification(
1426 io_object_t _service,
1427 io_name_t type_of_interest,
1428 mach_port_t port,
1429 io_async_ref_t reference,
1430 mach_msg_type_number_t referenceCnt,
1431 io_object_t * notification )
1432 {
1433
1434 IOServiceMessageUserNotification * userNotify = 0;
1435 IONotifier * notify = 0;
1436 const OSSymbol * sym;
1437 IOReturn err;
1438
1439 CHECK( IOService, _service, service );
1440
1441 err = kIOReturnNoResources;
1442 if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1443
1444 userNotify = new IOServiceMessageUserNotification;
1445
1446 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
1447 reference, kIOUserNotifyMaxMessageSize )) {
1448 userNotify->release();
1449 userNotify = 0;
1450 }
1451 if( !userNotify)
1452 continue;
1453
1454 notify = service->registerInterest( sym,
1455 &userNotify->_handler, userNotify );
1456 if( notify) {
1457 *notification = userNotify;
1458 userNotify->setNotification( notify );
1459 err = kIOReturnSuccess;
1460 } else
1461 err = kIOReturnUnsupported;
1462
1463 sym->release();
1464
1465 } while( false );
1466
1467 return( err );
1468 }
1469
1470 /* Routine io_service_acknowledge_notification */
1471 kern_return_t is_io_service_acknowledge_notification(
1472 io_object_t _service,
1473 natural_t notify_ref,
1474 natural_t response )
1475 {
1476 CHECK( IOService, _service, service );
1477
1478 return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1479 (IOOptionBits) response ));
1480
1481 }
1482
1483 /* Routine io_connect_get_semaphore */
1484 kern_return_t is_io_connect_get_notification_semaphore(
1485 io_connect_t connection,
1486 natural_t notification_type,
1487 semaphore_t *semaphore )
1488 {
1489 CHECK( IOUserClient, connection, client );
1490
1491 return( client->getNotificationSemaphore( (UInt32) notification_type,
1492 semaphore ));
1493 }
1494
1495 /* Routine io_registry_get_root_entry */
1496 kern_return_t is_io_registry_get_root_entry(
1497 mach_port_t master_port,
1498 io_object_t *root )
1499 {
1500 IORegistryEntry * entry;
1501
1502 if( master_port != master_device_port)
1503 return( kIOReturnNotPrivileged);
1504
1505 entry = IORegistryEntry::getRegistryRoot();
1506 if( entry)
1507 entry->retain();
1508 *root = entry;
1509
1510 return( kIOReturnSuccess );
1511 }
1512
1513 /* Routine io_registry_create_iterator */
1514 kern_return_t is_io_registry_create_iterator(
1515 mach_port_t master_port,
1516 io_name_t plane,
1517 int options,
1518 io_object_t *iterator )
1519 {
1520 if( master_port != master_device_port)
1521 return( kIOReturnNotPrivileged);
1522
1523 *iterator = IORegistryIterator::iterateOver(
1524 IORegistryEntry::getPlane( plane ), options );
1525
1526 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1527 }
1528
1529 /* Routine io_registry_entry_create_iterator */
1530 kern_return_t is_io_registry_entry_create_iterator(
1531 io_object_t registry_entry,
1532 io_name_t plane,
1533 int options,
1534 io_object_t *iterator )
1535 {
1536 CHECK( IORegistryEntry, registry_entry, entry );
1537
1538 *iterator = IORegistryIterator::iterateOver( entry,
1539 IORegistryEntry::getPlane( plane ), options );
1540
1541 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1542 }
1543
1544 /* Routine io_registry_iterator_enter */
1545 kern_return_t is_io_registry_iterator_enter_entry(
1546 io_object_t iterator )
1547 {
1548 CHECK( IORegistryIterator, iterator, iter );
1549
1550 iter->enterEntry();
1551
1552 return( kIOReturnSuccess );
1553 }
1554
1555 /* Routine io_registry_iterator_exit */
1556 kern_return_t is_io_registry_iterator_exit_entry(
1557 io_object_t iterator )
1558 {
1559 bool didIt;
1560
1561 CHECK( IORegistryIterator, iterator, iter );
1562
1563 didIt = iter->exitEntry();
1564
1565 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
1566 }
1567
1568 /* Routine io_registry_entry_from_path */
1569 kern_return_t is_io_registry_entry_from_path(
1570 mach_port_t master_port,
1571 io_string_t path,
1572 io_object_t *registry_entry )
1573 {
1574 IORegistryEntry * entry;
1575
1576 if( master_port != master_device_port)
1577 return( kIOReturnNotPrivileged);
1578
1579 entry = IORegistryEntry::fromPath( path );
1580
1581 *registry_entry = entry;
1582
1583 return( kIOReturnSuccess );
1584 }
1585
1586 /* Routine io_registry_entry_in_plane */
1587 kern_return_t is_io_registry_entry_in_plane(
1588 io_object_t registry_entry,
1589 io_name_t plane,
1590 boolean_t *inPlane )
1591 {
1592 CHECK( IORegistryEntry, registry_entry, entry );
1593
1594 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
1595
1596 return( kIOReturnSuccess );
1597 }
1598
1599
1600 /* Routine io_registry_entry_get_path */
1601 kern_return_t is_io_registry_entry_get_path(
1602 io_object_t registry_entry,
1603 io_name_t plane,
1604 io_string_t path )
1605 {
1606 int length;
1607 CHECK( IORegistryEntry, registry_entry, entry );
1608
1609 length = sizeof( io_string_t);
1610 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
1611 return( kIOReturnSuccess );
1612 else
1613 return( kIOReturnBadArgument );
1614 }
1615
1616
1617 /* Routine io_registry_entry_get_name */
1618 kern_return_t is_io_registry_entry_get_name(
1619 io_object_t registry_entry,
1620 io_name_t name )
1621 {
1622 CHECK( IORegistryEntry, registry_entry, entry );
1623
1624 strncpy( name, entry->getName(), sizeof( io_name_t));
1625
1626 return( kIOReturnSuccess );
1627 }
1628
1629 /* Routine io_registry_entry_get_name_in_plane */
1630 kern_return_t is_io_registry_entry_get_name_in_plane(
1631 io_object_t registry_entry,
1632 io_name_t planeName,
1633 io_name_t name )
1634 {
1635 const IORegistryPlane * plane;
1636 CHECK( IORegistryEntry, registry_entry, entry );
1637
1638 if( planeName[0])
1639 plane = IORegistryEntry::getPlane( planeName );
1640 else
1641 plane = 0;
1642
1643 strncpy( name, entry->getName( plane), sizeof( io_name_t));
1644
1645 return( kIOReturnSuccess );
1646 }
1647
1648 /* Routine io_registry_entry_get_location_in_plane */
1649 kern_return_t is_io_registry_entry_get_location_in_plane(
1650 io_object_t registry_entry,
1651 io_name_t planeName,
1652 io_name_t location )
1653 {
1654 const IORegistryPlane * plane;
1655 CHECK( IORegistryEntry, registry_entry, entry );
1656
1657 if( planeName[0])
1658 plane = IORegistryEntry::getPlane( planeName );
1659 else
1660 plane = 0;
1661
1662 const char * cstr = entry->getLocation( plane );
1663
1664 if( cstr) {
1665 strncpy( location, cstr, sizeof( io_name_t));
1666 return( kIOReturnSuccess );
1667 } else
1668 return( kIOReturnNotFound );
1669 }
1670
1671 // Create a vm_map_copy_t or kalloc'ed data for memory
1672 // to be copied out. ipc will free after the copyout.
1673
1674 static kern_return_t copyoutkdata( void * data, vm_size_t len,
1675 io_buf_ptr_t * buf )
1676 {
1677 kern_return_t err;
1678 vm_map_copy_t copy;
1679
1680 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
1681 false /* src_destroy */, &copy);
1682
1683 assert( err == KERN_SUCCESS );
1684 if( err == KERN_SUCCESS )
1685 *buf = (char *) copy;
1686
1687 return( err );
1688 }
1689
1690 /* Routine io_registry_entry_get_property */
1691 kern_return_t is_io_registry_entry_get_property_bytes(
1692 io_object_t registry_entry,
1693 io_name_t property_name,
1694 io_scalar_inband_t buf,
1695 mach_msg_type_number_t *dataCnt )
1696 {
1697 OSObject * obj;
1698 OSData * data;
1699 OSString * str;
1700 OSBoolean * boo;
1701 OSNumber * off;
1702 UInt64 offsetBytes;
1703 unsigned int len = 0;
1704 const void * bytes = 0;
1705 IOReturn ret = kIOReturnSuccess;
1706
1707 CHECK( IORegistryEntry, registry_entry, entry );
1708
1709 obj = entry->copyProperty(property_name);
1710 if( !obj)
1711 return( kIOReturnNoResources );
1712
1713 // One day OSData will be a common container base class
1714 // until then...
1715 if( (data = OSDynamicCast( OSData, obj ))) {
1716 len = data->getLength();
1717 bytes = data->getBytesNoCopy();
1718
1719 } else if( (str = OSDynamicCast( OSString, obj ))) {
1720 len = str->getLength() + 1;
1721 bytes = str->getCStringNoCopy();
1722
1723 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
1724 len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
1725 bytes = boo->isTrue() ? "Yes" : "No";
1726
1727 } else if( (off = OSDynamicCast( OSNumber, obj ))) {
1728 offsetBytes = off->unsigned64BitValue();
1729 len = off->numberOfBytes();
1730 bytes = &offsetBytes;
1731 #ifdef __BIG_ENDIAN__
1732 bytes = (const void *)
1733 (((UInt32) bytes) + (sizeof( UInt64) - len));
1734 #endif
1735
1736 } else
1737 ret = kIOReturnBadArgument;
1738
1739 if( bytes) {
1740 if( *dataCnt < len)
1741 ret = kIOReturnIPCError;
1742 else {
1743 *dataCnt = len;
1744 bcopy( bytes, buf, len );
1745 }
1746 }
1747 obj->release();
1748
1749 return( ret );
1750 }
1751
1752
1753 /* Routine io_registry_entry_get_property */
1754 kern_return_t is_io_registry_entry_get_property(
1755 io_object_t registry_entry,
1756 io_name_t property_name,
1757 io_buf_ptr_t *properties,
1758 mach_msg_type_number_t *propertiesCnt )
1759 {
1760 kern_return_t err;
1761 vm_size_t len;
1762 OSObject * obj;
1763
1764 CHECK( IORegistryEntry, registry_entry, entry );
1765
1766 obj = entry->copyProperty(property_name);
1767 if( !obj)
1768 return( kIOReturnNotFound );
1769
1770 OSSerialize * s = OSSerialize::withCapacity(4096);
1771 if( !s) {
1772 obj->release();
1773 return( kIOReturnNoMemory );
1774 }
1775 s->clearText();
1776
1777 if( obj->serialize( s )) {
1778 len = s->getLength();
1779 *propertiesCnt = len;
1780 err = copyoutkdata( s->text(), len, properties );
1781
1782 } else
1783 err = kIOReturnUnsupported;
1784
1785 s->release();
1786 obj->release();
1787
1788 return( err );
1789 }
1790
1791 /* Routine io_registry_entry_get_property_recursively */
1792 kern_return_t is_io_registry_entry_get_property_recursively(
1793 io_object_t registry_entry,
1794 io_name_t plane,
1795 io_name_t property_name,
1796 int options,
1797 io_buf_ptr_t *properties,
1798 mach_msg_type_number_t *propertiesCnt )
1799 {
1800 kern_return_t err;
1801 vm_size_t len;
1802 OSObject * obj;
1803
1804 CHECK( IORegistryEntry, registry_entry, entry );
1805
1806 obj = entry->copyProperty( property_name,
1807 IORegistryEntry::getPlane( plane ), options);
1808 if( !obj)
1809 return( kIOReturnNotFound );
1810
1811 OSSerialize * s = OSSerialize::withCapacity(4096);
1812 if( !s) {
1813 obj->release();
1814 return( kIOReturnNoMemory );
1815 }
1816
1817 s->clearText();
1818
1819 if( obj->serialize( s )) {
1820 len = s->getLength();
1821 *propertiesCnt = len;
1822 err = copyoutkdata( s->text(), len, properties );
1823
1824 } else
1825 err = kIOReturnUnsupported;
1826
1827 s->release();
1828 obj->release();
1829
1830 return( err );
1831 }
1832
1833 /* Routine io_registry_entry_get_properties */
1834 kern_return_t is_io_registry_entry_get_properties(
1835 io_object_t registry_entry,
1836 io_buf_ptr_t *properties,
1837 mach_msg_type_number_t *propertiesCnt )
1838 {
1839 kern_return_t err;
1840 vm_size_t len;
1841
1842 CHECK( IORegistryEntry, registry_entry, entry );
1843
1844 OSSerialize * s = OSSerialize::withCapacity(4096);
1845 if( !s)
1846 return( kIOReturnNoMemory );
1847
1848 s->clearText();
1849
1850 if( entry->serializeProperties( s )) {
1851 len = s->getLength();
1852 *propertiesCnt = len;
1853 err = copyoutkdata( s->text(), len, properties );
1854
1855 } else
1856 err = kIOReturnUnsupported;
1857
1858 s->release();
1859
1860 return( err );
1861 }
1862
1863 /* Routine io_registry_entry_set_properties */
1864 kern_return_t is_io_registry_entry_set_properties
1865 (
1866 io_object_t registry_entry,
1867 io_buf_ptr_t properties,
1868 mach_msg_type_number_t propertiesCnt,
1869 natural_t * result)
1870 {
1871 OSObject * obj;
1872 kern_return_t err;
1873 IOReturn res;
1874 vm_offset_t data;
1875 vm_map_offset_t map_data;
1876
1877 CHECK( IORegistryEntry, registry_entry, entry );
1878
1879 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
1880 data = CAST_DOWN(vm_offset_t, map_data);
1881
1882 if( KERN_SUCCESS == err) {
1883
1884 // must return success after vm_map_copyout() succeeds
1885 obj = OSUnserializeXML( (const char *) data );
1886 vm_deallocate( kernel_map, data, propertiesCnt );
1887
1888 if( obj) {
1889 res = entry->setProperties( obj );
1890 obj->release();
1891 } else
1892 res = kIOReturnBadArgument;
1893 } else
1894 res = err;
1895
1896 *result = res;
1897 return( err );
1898 }
1899
1900 /* Routine io_registry_entry_get_child_iterator */
1901 kern_return_t is_io_registry_entry_get_child_iterator(
1902 io_object_t registry_entry,
1903 io_name_t plane,
1904 io_object_t *iterator )
1905 {
1906 CHECK( IORegistryEntry, registry_entry, entry );
1907
1908 *iterator = entry->getChildIterator(
1909 IORegistryEntry::getPlane( plane ));
1910
1911 return( kIOReturnSuccess );
1912 }
1913
1914 /* Routine io_registry_entry_get_parent_iterator */
1915 kern_return_t is_io_registry_entry_get_parent_iterator(
1916 io_object_t registry_entry,
1917 io_name_t plane,
1918 io_object_t *iterator)
1919 {
1920 CHECK( IORegistryEntry, registry_entry, entry );
1921
1922 *iterator = entry->getParentIterator(
1923 IORegistryEntry::getPlane( plane ));
1924
1925 return( kIOReturnSuccess );
1926 }
1927
1928 /* Routine io_service_get_busy_state */
1929 kern_return_t is_io_service_get_busy_state(
1930 io_object_t _service,
1931 int *busyState )
1932 {
1933 CHECK( IOService, _service, service );
1934
1935 *busyState = service->getBusyState();
1936
1937 return( kIOReturnSuccess );
1938 }
1939
1940 /* Routine io_service_get_state */
1941 kern_return_t is_io_service_get_state(
1942 io_object_t _service,
1943 uint64_t *state )
1944 {
1945 CHECK( IOService, _service, service );
1946
1947 *state = service->getState();
1948
1949 return( kIOReturnSuccess );
1950 }
1951
1952 /* Routine io_service_wait_quiet */
1953 kern_return_t is_io_service_wait_quiet(
1954 io_object_t _service,
1955 mach_timespec_t wait_time )
1956 {
1957 CHECK( IOService, _service, service );
1958
1959 return( service->waitQuiet( &wait_time ));
1960 }
1961
1962 /* Routine io_service_request_probe */
1963 kern_return_t is_io_service_request_probe(
1964 io_object_t _service,
1965 int options )
1966 {
1967 CHECK( IOService, _service, service );
1968
1969 return( service->requestProbe( options ));
1970 }
1971
1972
1973 /* Routine io_service_open */
1974 kern_return_t is_io_service_open(
1975 io_object_t _service,
1976 task_t owningTask,
1977 int connect_type,
1978 io_object_t *connection )
1979 {
1980 IOUserClient * client;
1981 IOReturn err;
1982
1983 CHECK( IOService, _service, service );
1984
1985 err = service->newUserClient( owningTask, (void *) owningTask,
1986 connect_type, 0, &client );
1987
1988 if( err == kIOReturnSuccess) {
1989 assert( OSDynamicCast(IOUserClient, client) );
1990 *connection = client;
1991 }
1992
1993 return( err);
1994 }
1995
1996 /* Routine io_service_open_ndr */
1997 kern_return_t is_io_service_open_extended(
1998 io_object_t _service,
1999 task_t owningTask,
2000 int connect_type,
2001 NDR_record_t ndr,
2002 io_buf_ptr_t properties,
2003 mach_msg_type_number_t propertiesCnt,
2004 natural_t * result,
2005 io_object_t *connection )
2006 {
2007 IOUserClient * client = 0;
2008 kern_return_t err = KERN_SUCCESS;
2009 IOReturn res = kIOReturnSuccess;
2010 OSDictionary * propertiesDict = 0;
2011 bool crossEndian;
2012 bool disallowAccess;
2013
2014 CHECK( IOService, _service, service );
2015
2016 do
2017 {
2018 if (properties)
2019 {
2020 OSObject * obj;
2021 vm_offset_t data;
2022 vm_map_offset_t map_data;
2023
2024 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2025 res = err;
2026 data = CAST_DOWN(vm_offset_t, map_data);
2027 if (KERN_SUCCESS == err)
2028 {
2029 // must return success after vm_map_copyout() succeeds
2030 obj = OSUnserializeXML( (const char *) data );
2031 vm_deallocate( kernel_map, data, propertiesCnt );
2032 propertiesDict = OSDynamicCast(OSDictionary, obj);
2033 if (!propertiesDict)
2034 {
2035 res = kIOReturnBadArgument;
2036 if (obj)
2037 obj->release();
2038 }
2039 }
2040 if (kIOReturnSuccess != res)
2041 break;
2042 }
2043
2044 crossEndian = (ndr.int_rep != NDR_record.int_rep);
2045 if (crossEndian)
2046 {
2047 if (!propertiesDict)
2048 propertiesDict = OSDictionary::withCapacity(4);
2049 OSData * data = OSData::withBytes(&ndr, sizeof(ndr));
2050 if (data)
2051 {
2052 if (propertiesDict)
2053 propertiesDict->setObject(kIOUserClientCrossEndianKey, data);
2054 data->release();
2055 }
2056 }
2057
2058 res = service->newUserClient( owningTask, (void *) owningTask,
2059 connect_type, propertiesDict, &client );
2060
2061 if (propertiesDict)
2062 propertiesDict->release();
2063
2064 if (res == kIOReturnSuccess)
2065 {
2066 assert( OSDynamicCast(IOUserClient, client) );
2067
2068 disallowAccess = (crossEndian
2069 && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
2070 && (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
2071
2072 if (disallowAccess)
2073 {
2074 client->clientClose();
2075 client->release();
2076 client = 0;
2077 res = kIOReturnUnsupported;
2078 break;
2079 }
2080 client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
2081 }
2082 }
2083 while (false);
2084
2085 *connection = client;
2086 *result = res;
2087
2088 return (err);
2089 }
2090
2091 /* Routine io_service_close */
2092 kern_return_t is_io_service_close(
2093 io_object_t connection )
2094 {
2095 OSSet * mappings;
2096 if ((mappings = OSDynamicCast(OSSet, connection)))
2097 return( kIOReturnSuccess );
2098
2099 CHECK( IOUserClient, connection, client );
2100
2101 client->clientClose();
2102
2103 return( kIOReturnSuccess );
2104 }
2105
2106 /* Routine io_connect_get_service */
2107 kern_return_t is_io_connect_get_service(
2108 io_object_t connection,
2109 io_object_t *service )
2110 {
2111 IOService * theService;
2112
2113 CHECK( IOUserClient, connection, client );
2114
2115 theService = client->getService();
2116 if( theService)
2117 theService->retain();
2118
2119 *service = theService;
2120
2121 return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
2122 }
2123
2124 /* Routine io_connect_set_notification_port */
2125 kern_return_t is_io_connect_set_notification_port(
2126 io_object_t connection,
2127 int notification_type,
2128 mach_port_t port,
2129 int reference)
2130 {
2131 CHECK( IOUserClient, connection, client );
2132
2133 return( client->registerNotificationPort( port, notification_type,
2134 reference ));
2135 }
2136
2137 kern_return_t is_io_connect_map_memory(
2138 io_object_t connect,
2139 int type,
2140 task_t task,
2141 vm_address_t * mapAddr,
2142 vm_size_t * mapSize,
2143 int flags )
2144 {
2145 IOReturn err;
2146 IOMemoryMap * map;
2147
2148 CHECK( IOUserClient, connect, client );
2149
2150 map = client->mapClientMemory( type, task, flags, *mapAddr );
2151
2152 if( map) {
2153 *mapAddr = map->getVirtualAddress();
2154 if( mapSize)
2155 *mapSize = map->getLength();
2156
2157 if( client->sharedInstance
2158 || (task != current_task())) {
2159 // push a name out to the task owning the map,
2160 // so we can clean up maps
2161 #if IOASSERT
2162 mach_port_name_t name =
2163 #endif
2164 IOMachPort::makeSendRightForTask(
2165 task, map, IKOT_IOKIT_OBJECT );
2166 assert( name );
2167
2168 } else {
2169 // keep it with the user client
2170 IOLockLock( gIOObjectPortLock);
2171 if( 0 == client->mappings)
2172 client->mappings = OSSet::withCapacity(2);
2173 if( client->mappings)
2174 client->mappings->setObject( map);
2175 IOLockUnlock( gIOObjectPortLock);
2176 map->release();
2177 }
2178 err = kIOReturnSuccess;
2179
2180 } else
2181 err = kIOReturnBadArgument;
2182
2183 return( err );
2184 }
2185
2186 IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
2187 {
2188 OSIterator * iter;
2189 IOMemoryMap * map = 0;
2190
2191 IOLockLock(gIOObjectPortLock);
2192
2193 iter = OSCollectionIterator::withCollection(mappings);
2194 if(iter)
2195 {
2196 while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject())))
2197 {
2198 if(mem == map->getMemoryDescriptor())
2199 {
2200 map->retain();
2201 mappings->removeObject(map);
2202 break;
2203 }
2204 }
2205 iter->release();
2206 }
2207
2208 IOLockUnlock(gIOObjectPortLock);
2209
2210 return (map);
2211 }
2212
2213 kern_return_t is_io_connect_unmap_memory(
2214 io_object_t connect,
2215 int type,
2216 task_t task,
2217 vm_address_t mapAddr )
2218 {
2219 IOReturn err;
2220 IOOptionBits options = 0;
2221 IOMemoryDescriptor * memory;
2222 IOMemoryMap * map;
2223
2224 CHECK( IOUserClient, connect, client );
2225
2226 err = client->clientMemoryForType( (UInt32) type, &options, &memory );
2227
2228 if( memory && (kIOReturnSuccess == err)) {
2229
2230 options = (options & ~kIOMapUserOptionsMask)
2231 | kIOMapAnywhere | kIOMapReference;
2232
2233 map = memory->map( task, mapAddr, options );
2234 memory->release();
2235 if( map)
2236 {
2237 IOLockLock( gIOObjectPortLock);
2238 if( client->mappings)
2239 client->mappings->removeObject( map);
2240 IOLockUnlock( gIOObjectPortLock);
2241
2242 mach_port_name_t name = 0;
2243 if (task != current_task())
2244 name = IOMachPort::makeSendRightForTask( task, map, IKOT_IOKIT_OBJECT );
2245 if (name)
2246 {
2247 map->unmap();
2248 err = iokit_mod_send_right( task, name, -2 );
2249 err = kIOReturnSuccess;
2250 }
2251 else
2252 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
2253 if (task == current_task())
2254 map->release();
2255 }
2256 else
2257 err = kIOReturnBadArgument;
2258 }
2259
2260 return( err );
2261 }
2262
2263
2264 /* Routine io_connect_add_client */
2265 kern_return_t is_io_connect_add_client(
2266 io_object_t connection,
2267 io_object_t connect_to)
2268 {
2269 CHECK( IOUserClient, connection, client );
2270 CHECK( IOUserClient, connect_to, to );
2271
2272 return( client->connectClient( to ) );
2273 }
2274
2275
2276 /* Routine io_connect_set_properties */
2277 kern_return_t is_io_connect_set_properties(
2278 io_object_t connection,
2279 io_buf_ptr_t properties,
2280 mach_msg_type_number_t propertiesCnt,
2281 natural_t * result)
2282 {
2283 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
2284 }
2285
2286
2287 /* Routine io_connect_method_scalarI_scalarO */
2288 kern_return_t is_io_connect_method_scalarI_scalarO(
2289 io_object_t connect,
2290 UInt32 index,
2291 void * input[],
2292 IOByteCount inputCount,
2293 void * output[],
2294 IOByteCount * outputCount )
2295 {
2296 IOReturn err;
2297 IOExternalMethod * method;
2298 IOService * object;
2299 IOMethod func;
2300
2301 CHECK( IOUserClient, connect, client);
2302 if( (method = client->getTargetAndMethodForIndex(&object, index))) {
2303 do {
2304 err = kIOReturnBadArgument;
2305 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
2306 continue;
2307 if( inputCount != method->count0)
2308 continue;
2309 if( *outputCount != method->count1)
2310 continue;
2311
2312 func = method->func;
2313
2314 switch( inputCount) {
2315
2316 case 6:
2317 err = (object->*func)( input[0], input[1], input[2],
2318 input[3], input[4], input[5] );
2319 break;
2320 case 5:
2321 err = (object->*func)( input[0], input[1], input[2],
2322 input[3], input[4],
2323 &output[0] );
2324 break;
2325 case 4:
2326 err = (object->*func)( input[0], input[1], input[2],
2327 input[3],
2328 &output[0], &output[1] );
2329 break;
2330 case 3:
2331 err = (object->*func)( input[0], input[1], input[2],
2332 &output[0], &output[1], &output[2] );
2333 break;
2334 case 2:
2335 err = (object->*func)( input[0], input[1],
2336 &output[0], &output[1], &output[2],
2337 &output[3] );
2338 break;
2339 case 1:
2340 err = (object->*func)( input[0],
2341 &output[0], &output[1], &output[2],
2342 &output[3], &output[4] );
2343 break;
2344 case 0:
2345 err = (object->*func)( &output[0], &output[1], &output[2],
2346 &output[3], &output[4], &output[5] );
2347 break;
2348
2349 default:
2350 IOLog("%s: Bad method table\n", client->getName());
2351 }
2352 } while( false);
2353
2354 } else
2355 err = kIOReturnUnsupported;
2356
2357 return( err);
2358 }
2359
2360 /* Routine io_connect_method_scalarI_structureO */
2361 kern_return_t is_io_connect_method_scalarI_structureO(
2362 io_object_t connect,
2363 UInt32 index,
2364 void * input[],
2365 IOByteCount inputCount,
2366 void * output,
2367 IOByteCount * outputCount )
2368 {
2369 IOReturn err;
2370 IOExternalMethod * method;
2371 IOService * object;
2372 IOMethod func;
2373
2374 CHECK( IOUserClient, connect, client);
2375
2376 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2377 do {
2378 err = kIOReturnBadArgument;
2379 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
2380 continue;
2381 if( inputCount != method->count0)
2382 continue;
2383 if( (0xffffffff != method->count1)
2384 && (*outputCount != method->count1))
2385 continue;
2386
2387 func = method->func;
2388
2389 switch( inputCount) {
2390
2391 case 5:
2392 err = (object->*func)( input[0], input[1], input[2],
2393 input[3], input[4],
2394 output );
2395 break;
2396 case 4:
2397 err = (object->*func)( input[0], input[1], input[2],
2398 input[3],
2399 output, (void *)outputCount );
2400 break;
2401 case 3:
2402 err = (object->*func)( input[0], input[1], input[2],
2403 output, (void *)outputCount, 0 );
2404 break;
2405 case 2:
2406 err = (object->*func)( input[0], input[1],
2407 output, (void *)outputCount, 0, 0 );
2408 break;
2409 case 1:
2410 err = (object->*func)( input[0],
2411 output, (void *)outputCount, 0, 0, 0 );
2412 break;
2413 case 0:
2414 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 );
2415 break;
2416
2417 default:
2418 IOLog("%s: Bad method table\n", client->getName());
2419 }
2420 } while( false);
2421
2422 } else
2423 err = kIOReturnUnsupported;
2424
2425 return( err);
2426 }
2427
2428 /* Routine io_connect_method_scalarI_structureI */
2429 kern_return_t is_io_connect_method_scalarI_structureI(
2430 io_connect_t connect,
2431 UInt32 index,
2432 void * input[],
2433 IOByteCount inputCount,
2434 UInt8 * inputStruct,
2435 IOByteCount inputStructCount )
2436 {
2437 IOReturn err;
2438 IOExternalMethod * method;
2439 IOService * object;
2440 IOMethod func;
2441
2442 CHECK( IOUserClient, connect, client);
2443
2444 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2445 do {
2446 err = kIOReturnBadArgument;
2447 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
2448 continue;
2449 if( (0xffffffff != method->count0)
2450 && (inputCount != method->count0))
2451 continue;
2452 if( (0xffffffff != method->count1)
2453 && (inputStructCount != method->count1))
2454 continue;
2455
2456 func = method->func;
2457
2458 switch( inputCount) {
2459
2460 case 5:
2461 err = (object->*func)( input[0], input[1], input[2],
2462 input[3], input[4],
2463 inputStruct );
2464 break;
2465 case 4:
2466 err = (object->*func)( input[0], input[1], input[2],
2467 input[3],
2468 inputStruct, (void *)inputStructCount );
2469 break;
2470 case 3:
2471 err = (object->*func)( input[0], input[1], input[2],
2472 inputStruct, (void *)inputStructCount,
2473 0 );
2474 break;
2475 case 2:
2476 err = (object->*func)( input[0], input[1],
2477 inputStruct, (void *)inputStructCount,
2478 0, 0 );
2479 break;
2480 case 1:
2481 err = (object->*func)( input[0],
2482 inputStruct, (void *)inputStructCount,
2483 0, 0, 0 );
2484 break;
2485 case 0:
2486 err = (object->*func)( inputStruct, (void *)inputStructCount,
2487 0, 0, 0, 0 );
2488 break;
2489
2490 default:
2491 IOLog("%s: Bad method table\n", client->getName());
2492 }
2493 } while( false);
2494
2495 } else
2496 err = kIOReturnUnsupported;
2497
2498 return( err);
2499 }
2500
2501 /* Routine io_connect_method_structureI_structureO */
2502 kern_return_t is_io_connect_method_structureI_structureO(
2503 io_object_t connect,
2504 UInt32 index,
2505 UInt8 * input,
2506 IOByteCount inputCount,
2507 UInt8 * output,
2508 IOByteCount * outputCount )
2509 {
2510 IOReturn err;
2511 IOExternalMethod * method;
2512 IOService * object;
2513 IOMethod func;
2514
2515 CHECK( IOUserClient, connect, client);
2516
2517 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
2518 do {
2519 err = kIOReturnBadArgument;
2520 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
2521 continue;
2522 if( (0xffffffff != method->count0)
2523 && (inputCount != method->count0))
2524 continue;
2525 if( (0xffffffff != method->count1)
2526 && (*outputCount != method->count1))
2527 continue;
2528
2529 func = method->func;
2530
2531 if( method->count1) {
2532 if( method->count0) {
2533 err = (object->*func)( input, output,
2534 (void *)inputCount, outputCount, 0, 0 );
2535 } else {
2536 err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
2537 }
2538 } else {
2539 err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
2540 }
2541
2542 } while( false);
2543
2544 } else
2545 err = kIOReturnUnsupported;
2546
2547 return( err);
2548 }
2549
2550 kern_return_t is_io_async_method_scalarI_scalarO(
2551 io_object_t connect,
2552 mach_port_t wakePort,
2553 io_async_ref_t reference,
2554 mach_msg_type_number_t referenceCnt,
2555 UInt32 index,
2556 void * input[],
2557 IOByteCount inputCount,
2558 void * output[],
2559 IOByteCount * outputCount )
2560 {
2561 IOReturn err;
2562 IOExternalAsyncMethod *method;
2563 IOService * object;
2564 IOAsyncMethod func;
2565
2566 CHECK( IOUserClient, connect, client);
2567 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2568 do {
2569 err = kIOReturnBadArgument;
2570 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
2571 continue;
2572 if( inputCount != method->count0)
2573 continue;
2574 if( *outputCount != method->count1)
2575 continue;
2576
2577 reference[0] = (natural_t) wakePort;
2578 func = method->func;
2579
2580 switch( inputCount) {
2581
2582 case 6:
2583 err = (object->*func)( reference,
2584 input[0], input[1], input[2],
2585 input[3], input[4], input[5] );
2586 break;
2587 case 5:
2588 err = (object->*func)( reference,
2589 input[0], input[1], input[2],
2590 input[3], input[4],
2591 &output[0] );
2592 break;
2593 case 4:
2594 err = (object->*func)( reference,
2595 input[0], input[1], input[2],
2596 input[3],
2597 &output[0], &output[1] );
2598 break;
2599 case 3:
2600 err = (object->*func)( reference,
2601 input[0], input[1], input[2],
2602 &output[0], &output[1], &output[2] );
2603 break;
2604 case 2:
2605 err = (object->*func)( reference,
2606 input[0], input[1],
2607 &output[0], &output[1], &output[2],
2608 &output[3] );
2609 break;
2610 case 1:
2611 err = (object->*func)( reference,
2612 input[0],
2613 &output[0], &output[1], &output[2],
2614 &output[3], &output[4] );
2615 break;
2616 case 0:
2617 err = (object->*func)( reference,
2618 &output[0], &output[1], &output[2],
2619 &output[3], &output[4], &output[5] );
2620 break;
2621
2622 default:
2623 IOLog("%s: Bad method table\n", client->getName());
2624 }
2625 } while( false);
2626
2627 } else
2628 err = kIOReturnUnsupported;
2629
2630 return( err);
2631 }
2632
2633 kern_return_t is_io_async_method_scalarI_structureO(
2634 io_object_t connect,
2635 mach_port_t wakePort,
2636 io_async_ref_t reference,
2637 mach_msg_type_number_t referenceCnt,
2638 UInt32 index,
2639 void * input[],
2640 IOByteCount inputCount,
2641 void * output,
2642 IOByteCount * outputCount )
2643 {
2644 IOReturn err;
2645 IOExternalAsyncMethod *method;
2646 IOService * object;
2647 IOAsyncMethod func;
2648
2649 CHECK( IOUserClient, connect, client);
2650
2651 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2652 do {
2653 err = kIOReturnBadArgument;
2654 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
2655 continue;
2656 if( inputCount != method->count0)
2657 continue;
2658 if( (0xffffffff != method->count1)
2659 && (*outputCount != method->count1))
2660 continue;
2661
2662 reference[0] = (natural_t) wakePort;
2663 func = method->func;
2664
2665 switch( inputCount) {
2666
2667 case 5:
2668 err = (object->*func)( reference,
2669 input[0], input[1], input[2],
2670 input[3], input[4],
2671 output );
2672 break;
2673 case 4:
2674 err = (object->*func)( reference,
2675 input[0], input[1], input[2],
2676 input[3],
2677 output, (void *)outputCount );
2678 break;
2679 case 3:
2680 err = (object->*func)( reference,
2681 input[0], input[1], input[2],
2682 output, (void *)outputCount, 0 );
2683 break;
2684 case 2:
2685 err = (object->*func)( reference,
2686 input[0], input[1],
2687 output, (void *)outputCount, 0, 0 );
2688 break;
2689 case 1:
2690 err = (object->*func)( reference,
2691 input[0],
2692 output, (void *)outputCount, 0, 0, 0 );
2693 break;
2694 case 0:
2695 err = (object->*func)( reference,
2696 output, (void *)outputCount, 0, 0, 0, 0 );
2697 break;
2698
2699 default:
2700 IOLog("%s: Bad method table\n", client->getName());
2701 }
2702 } while( false);
2703
2704 } else
2705 err = kIOReturnUnsupported;
2706
2707 return( err);
2708 }
2709
2710 kern_return_t is_io_async_method_scalarI_structureI(
2711 io_connect_t connect,
2712 mach_port_t wakePort,
2713 io_async_ref_t reference,
2714 mach_msg_type_number_t referenceCnt,
2715 UInt32 index,
2716 void * input[],
2717 IOByteCount inputCount,
2718 UInt8 * inputStruct,
2719 IOByteCount inputStructCount )
2720 {
2721 IOReturn err;
2722 IOExternalAsyncMethod *method;
2723 IOService * object;
2724 IOAsyncMethod func;
2725
2726 CHECK( IOUserClient, connect, client);
2727
2728 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2729 do {
2730 err = kIOReturnBadArgument;
2731 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
2732 continue;
2733 if( (0xffffffff != method->count0)
2734 && (inputCount != method->count0))
2735 continue;
2736 if( (0xffffffff != method->count1)
2737 && (inputStructCount != method->count1))
2738 continue;
2739
2740 reference[0] = (natural_t) wakePort;
2741 func = method->func;
2742
2743 switch( inputCount) {
2744
2745 case 5:
2746 err = (object->*func)( reference,
2747 input[0], input[1], input[2],
2748 input[3], input[4],
2749 inputStruct );
2750 break;
2751 case 4:
2752 err = (object->*func)( reference,
2753 input[0], input[1], input[2],
2754 input[3],
2755 inputStruct, (void *)inputStructCount );
2756 break;
2757 case 3:
2758 err = (object->*func)( reference,
2759 input[0], input[1], input[2],
2760 inputStruct, (void *)inputStructCount,
2761 0 );
2762 break;
2763 case 2:
2764 err = (object->*func)( reference,
2765 input[0], input[1],
2766 inputStruct, (void *)inputStructCount,
2767 0, 0 );
2768 break;
2769 case 1:
2770 err = (object->*func)( reference,
2771 input[0],
2772 inputStruct, (void *)inputStructCount,
2773 0, 0, 0 );
2774 break;
2775 case 0:
2776 err = (object->*func)( reference,
2777 inputStruct, (void *)inputStructCount,
2778 0, 0, 0, 0 );
2779 break;
2780
2781 default:
2782 IOLog("%s: Bad method table\n", client->getName());
2783 }
2784 } while( false);
2785
2786 } else
2787 err = kIOReturnUnsupported;
2788
2789 return( err);
2790 }
2791
2792 kern_return_t is_io_async_method_structureI_structureO(
2793 io_object_t connect,
2794 mach_port_t wakePort,
2795 io_async_ref_t reference,
2796 mach_msg_type_number_t referenceCnt,
2797 UInt32 index,
2798 UInt8 * input,
2799 IOByteCount inputCount,
2800 UInt8 * output,
2801 IOByteCount * outputCount )
2802 {
2803 IOReturn err;
2804 IOExternalAsyncMethod *method;
2805 IOService * object;
2806 IOAsyncMethod func;
2807
2808 CHECK( IOUserClient, connect, client);
2809
2810 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2811 do {
2812 err = kIOReturnBadArgument;
2813 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
2814 continue;
2815 if( (0xffffffff != method->count0)
2816 && (inputCount != method->count0))
2817 continue;
2818 if( (0xffffffff != method->count1)
2819 && (*outputCount != method->count1))
2820 continue;
2821
2822 reference[0] = (natural_t) wakePort;
2823 func = method->func;
2824
2825 if( method->count1) {
2826 if( method->count0) {
2827 err = (object->*func)( reference,
2828 input, output,
2829 (void *)inputCount, outputCount, 0, 0 );
2830 } else {
2831 err = (object->*func)( reference,
2832 output, outputCount, 0, 0, 0, 0 );
2833 }
2834 } else {
2835 err = (object->*func)( reference,
2836 input, (void *)inputCount, 0, 0, 0, 0 );
2837 }
2838
2839 } while( false);
2840
2841 } else
2842 err = kIOReturnUnsupported;
2843
2844 return( err);
2845 }
2846 /* Routine io_make_matching */
2847 kern_return_t is_io_make_matching(
2848 mach_port_t master_port,
2849 UInt32 type,
2850 IOOptionBits options,
2851 UInt8 * input,
2852 IOByteCount inputCount,
2853 io_string_t matching )
2854 {
2855 OSSerialize * s;
2856 IOReturn err = kIOReturnSuccess;
2857 OSDictionary * dict;
2858
2859 if( master_port != master_device_port)
2860 return( kIOReturnNotPrivileged);
2861
2862 switch( type) {
2863
2864 case kIOServiceMatching:
2865 dict = IOService::serviceMatching( gIOServiceKey );
2866 break;
2867
2868 case kIOBSDNameMatching:
2869 dict = IOBSDNameMatching( (const char *) input );
2870 break;
2871
2872 case kIOOFPathMatching:
2873 dict = IOOFPathMatching( (const char *) input,
2874 matching, sizeof( io_string_t));
2875 break;
2876
2877 default:
2878 dict = 0;
2879 }
2880
2881 if( !dict)
2882 return( kIOReturnUnsupported);
2883
2884 do {
2885 s = OSSerialize::withCapacity(4096);
2886 if( !s) {
2887 err = kIOReturnNoMemory;
2888 continue;
2889 }
2890 s->clearText();
2891 if( !dict->serialize( s )) {
2892 err = kIOReturnUnsupported;
2893 continue;
2894 }
2895
2896 if( s->getLength() > sizeof( io_string_t)) {
2897 err = kIOReturnNoMemory;
2898 continue;
2899 } else
2900 strcpy( matching, s->text());
2901
2902 } while( false);
2903
2904 if( s)
2905 s->release();
2906 if( dict)
2907 dict->release();
2908
2909 return( err);
2910 }
2911
2912 /* Routine io_catalog_send_data */
2913 kern_return_t is_io_catalog_send_data(
2914 mach_port_t master_port,
2915 int flag,
2916 io_buf_ptr_t inData,
2917 mach_msg_type_number_t inDataCount,
2918 natural_t * result)
2919 {
2920 OSObject * obj = 0;
2921 vm_offset_t data;
2922 kern_return_t kr = kIOReturnError;
2923
2924 //printf("io_catalog_send_data called. flag: %d\n", flag);
2925
2926 if( master_port != master_device_port)
2927 return kIOReturnNotPrivileged;
2928
2929 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2930 if(flag != kIOCatalogRemoveKernelLinker && ( !inData || !inDataCount) )
2931 return kIOReturnBadArgument;
2932
2933 if (inData) {
2934 vm_map_offset_t map_data;
2935
2936 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
2937 data = CAST_DOWN(vm_offset_t, map_data);
2938
2939 if( kr != KERN_SUCCESS)
2940 return kr;
2941
2942 // must return success after vm_map_copyout() succeeds
2943
2944 if( inDataCount ) {
2945 obj = (OSObject *)OSUnserializeXML((const char *)data);
2946 vm_deallocate( kernel_map, data, inDataCount );
2947 if( !obj) {
2948 *result = kIOReturnNoMemory;
2949 return( KERN_SUCCESS);
2950 }
2951 }
2952 }
2953
2954 switch ( flag ) {
2955 case kIOCatalogAddDrivers:
2956 case kIOCatalogAddDriversNoMatch: {
2957 OSArray * array;
2958
2959 array = OSDynamicCast(OSArray, obj);
2960 if ( array ) {
2961 if ( !gIOCatalogue->addDrivers( array ,
2962 flag == kIOCatalogAddDrivers) ) {
2963 kr = kIOReturnError;
2964 }
2965 }
2966 else {
2967 kr = kIOReturnBadArgument;
2968 }
2969 }
2970 break;
2971
2972 case kIOCatalogRemoveDrivers:
2973 case kIOCatalogRemoveDriversNoMatch: {
2974 OSDictionary * dict;
2975
2976 dict = OSDynamicCast(OSDictionary, obj);
2977 if ( dict ) {
2978 if ( !gIOCatalogue->removeDrivers( dict,
2979 flag == kIOCatalogRemoveDrivers ) ) {
2980 kr = kIOReturnError;
2981 }
2982 }
2983 else {
2984 kr = kIOReturnBadArgument;
2985 }
2986 }
2987 break;
2988
2989 case kIOCatalogStartMatching: {
2990 OSDictionary * dict;
2991
2992 dict = OSDynamicCast(OSDictionary, obj);
2993 if ( dict ) {
2994 if ( !gIOCatalogue->startMatching( dict ) ) {
2995 kr = kIOReturnError;
2996 }
2997 }
2998 else {
2999 kr = kIOReturnBadArgument;
3000 }
3001 }
3002 break;
3003
3004 case kIOCatalogRemoveKernelLinker: {
3005 if (gIOCatalogue->removeKernelLinker() != KERN_SUCCESS) {
3006 kr = kIOReturnError;
3007 } else {
3008 kr = kIOReturnSuccess;
3009 }
3010 }
3011 break;
3012
3013 default:
3014 kr = kIOReturnBadArgument;
3015 break;
3016 }
3017
3018 if (obj) obj->release();
3019
3020 *result = kr;
3021 return( KERN_SUCCESS);
3022 }
3023
3024 /* Routine io_catalog_terminate */
3025 kern_return_t is_io_catalog_terminate(
3026 mach_port_t master_port,
3027 int flag,
3028 io_name_t name )
3029 {
3030 kern_return_t kr;
3031
3032 if( master_port != master_device_port )
3033 return kIOReturnNotPrivileged;
3034
3035 kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
3036 kIOClientPrivilegeAdministrator );
3037 if( kIOReturnSuccess != kr)
3038 return( kr );
3039
3040 switch ( flag ) {
3041 case kIOCatalogServiceTerminate:
3042 OSIterator * iter;
3043 IOService * service;
3044
3045 iter = IORegistryIterator::iterateOver(gIOServicePlane,
3046 kIORegistryIterateRecursively);
3047 if ( !iter )
3048 return kIOReturnNoMemory;
3049
3050 do {
3051 iter->reset();
3052 while( (service = (IOService *)iter->getNextObject()) ) {
3053 if( service->metaCast(name)) {
3054 if ( !service->terminate( kIOServiceRequired
3055 | kIOServiceSynchronous) ) {
3056 kr = kIOReturnUnsupported;
3057 break;
3058 }
3059 }
3060 }
3061 } while( !service && !iter->isValid());
3062 iter->release();
3063 break;
3064
3065 case kIOCatalogModuleUnload:
3066 case kIOCatalogModuleTerminate:
3067 kr = gIOCatalogue->terminateDriversForModule(name,
3068 flag == kIOCatalogModuleUnload);
3069 break;
3070
3071 default:
3072 kr = kIOReturnBadArgument;
3073 break;
3074 }
3075
3076 return( kr );
3077 }
3078
3079 /* Routine io_catalog_get_data */
3080 kern_return_t is_io_catalog_get_data(
3081 mach_port_t master_port,
3082 int flag,
3083 io_buf_ptr_t *outData,
3084 mach_msg_type_number_t *outDataCount)
3085 {
3086 kern_return_t kr = kIOReturnSuccess;
3087 OSSerialize * s;
3088
3089 if( master_port != master_device_port)
3090 return kIOReturnNotPrivileged;
3091
3092 //printf("io_catalog_get_data called. flag: %d\n", flag);
3093
3094 s = OSSerialize::withCapacity(4096);
3095 if ( !s )
3096 return kIOReturnNoMemory;
3097
3098 s->clearText();
3099
3100 kr = gIOCatalogue->serializeData(flag, s);
3101
3102 if ( kr == kIOReturnSuccess ) {
3103 vm_offset_t data;
3104 vm_map_copy_t copy;
3105 vm_size_t size;
3106
3107 size = s->getLength();
3108 kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
3109 if ( kr == kIOReturnSuccess ) {
3110 bcopy(s->text(), (void *)data, size);
3111 kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
3112 (vm_map_size_t)size, true, &copy);
3113 *outData = (char *)copy;
3114 *outDataCount = size;
3115 }
3116 }
3117
3118 s->release();
3119
3120 return kr;
3121 }
3122
3123 /* Routine io_catalog_get_gen_count */
3124 kern_return_t is_io_catalog_get_gen_count(
3125 mach_port_t master_port,
3126 int *genCount)
3127 {
3128 if( master_port != master_device_port)
3129 return kIOReturnNotPrivileged;
3130
3131 //printf("io_catalog_get_gen_count called.\n");
3132
3133 if ( !genCount )
3134 return kIOReturnBadArgument;
3135
3136 *genCount = gIOCatalogue->getGenerationCount();
3137
3138 return kIOReturnSuccess;
3139 }
3140
3141 /* Routine io_catalog_module_loaded */
3142 kern_return_t is_io_catalog_module_loaded(
3143 mach_port_t master_port,
3144 io_name_t name)
3145 {
3146 if( master_port != master_device_port)
3147 return kIOReturnNotPrivileged;
3148
3149 //printf("io_catalog_module_loaded called. name %s\n", name);
3150
3151 if ( !name )
3152 return kIOReturnBadArgument;
3153
3154 gIOCatalogue->moduleHasLoaded(name);
3155
3156 return kIOReturnSuccess;
3157 }
3158
3159 kern_return_t is_io_catalog_reset(
3160 mach_port_t master_port,
3161 int flag)
3162 {
3163 if( master_port != master_device_port)
3164 return kIOReturnNotPrivileged;
3165
3166 switch ( flag ) {
3167 case kIOCatalogResetDefault:
3168 gIOCatalogue->reset();
3169 break;
3170
3171 default:
3172 return kIOReturnBadArgument;
3173 }
3174
3175 return kIOReturnSuccess;
3176 }
3177
3178 kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
3179 {
3180 kern_return_t result = kIOReturnBadArgument;
3181 IOUserClient *userClient;
3182
3183 if ((userClient = OSDynamicCast(IOUserClient,
3184 iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
3185 IOExternalTrap *trap;
3186 IOService *target = NULL;
3187
3188 trap = userClient->getTargetAndTrapForIndex(&target, args->index);
3189
3190 if (trap && target) {
3191 IOTrap func;
3192
3193 func = trap->func;
3194
3195 if (func) {
3196 result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
3197 }
3198 }
3199
3200 userClient->release();
3201 }
3202
3203 return result;
3204 }
3205
3206 }; /* extern "C" */
3207
3208 OSMetaClassDefineReservedUnused(IOUserClient, 0);
3209 OSMetaClassDefineReservedUnused(IOUserClient, 1);
3210 OSMetaClassDefineReservedUnused(IOUserClient, 2);
3211 OSMetaClassDefineReservedUnused(IOUserClient, 3);
3212 OSMetaClassDefineReservedUnused(IOUserClient, 4);
3213 OSMetaClassDefineReservedUnused(IOUserClient, 5);
3214 OSMetaClassDefineReservedUnused(IOUserClient, 6);
3215 OSMetaClassDefineReservedUnused(IOUserClient, 7);
3216 OSMetaClassDefineReservedUnused(IOUserClient, 8);
3217 OSMetaClassDefineReservedUnused(IOUserClient, 9);
3218 OSMetaClassDefineReservedUnused(IOUserClient, 10);
3219 OSMetaClassDefineReservedUnused(IOUserClient, 11);
3220 OSMetaClassDefineReservedUnused(IOUserClient, 12);
3221 OSMetaClassDefineReservedUnused(IOUserClient, 13);
3222 OSMetaClassDefineReservedUnused(IOUserClient, 14);
3223 OSMetaClassDefineReservedUnused(IOUserClient, 15);
3224