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