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