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