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