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