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