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