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