]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOUserClient.cpp
83e846bca221745a05a7f8cc68e655fae2767e03
[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 #include <IOKit/pci/IOPCIDevice.h>
806
807 static void makeMatchingCompatible( OSDictionary * dict )
808 {
809 const char * key;
810 const char * newKey;
811 OSObject * value;
812 OSString * str;
813 int i = 0;
814
815 static const char * gratuitousNameChanges[] = {
816 "IOImports", kIOProviderClassKey,
817 "IOClass Names", kIOClassKey,
818 "IOProbe Score", kIOProbeScoreKey,
819 "IOKit Debug", kIOKitDebugKey,
820 "IONeededResources", kIOResourceMatchKey,
821 "IOName Match", kIONameMatchKey,
822 "IOPCI Match", kIOPCIMatchKey,
823 "IOPCI Primary Match", kIOPCIPrimaryMatchKey,
824 "IOPCI Secondary Match",kIOPCISecondaryMatchKey,
825 "IOPCI Class Match", kIOPCIClassMatchKey,
826 0
827 };
828
829 while( (key = gratuitousNameChanges[i++])) {
830 newKey = gratuitousNameChanges[i++];
831 if( (value = dict->getObject( key))
832 && (0 == dict->getObject( newKey))) {
833
834 dict->setObject( newKey, value);
835 dict->removeObject( key);
836
837 if( (str = OSDynamicCast(OSString, dict->getObject("CFBundleIdentifier"))))
838 IOLog("kext \"%s\" ", str->getCStringNoCopy());
839 IOLog("must change \"%s\" to \"%s\"\n", key, newKey);
840 }
841 }
842 }
843
844 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
845
846 extern "C" {
847
848 #define CHECK(cls,obj,out) \
849 cls * out; \
850 if( !(out = OSDynamicCast( cls, obj))) \
851 return( kIOReturnBadArgument )
852
853 /* Routine io_object_get_class */
854 kern_return_t is_io_object_get_class(
855 io_object_t object,
856 io_name_t className )
857 {
858 if( !object)
859 return( kIOReturnBadArgument );
860
861 strcpy( className, object->getMetaClass()->getClassName());
862 return( kIOReturnSuccess );
863 }
864
865 /* Routine io_object_conforms_to */
866 kern_return_t is_io_object_conforms_to(
867 io_object_t object,
868 io_name_t className,
869 boolean_t *conforms )
870 {
871 if( !object)
872 return( kIOReturnBadArgument );
873
874 *conforms = (0 != object->metaCast( className ));
875 return( kIOReturnSuccess );
876 }
877
878 /* Routine io_object_get_retain_count */
879 kern_return_t is_io_object_get_retain_count(
880 io_object_t object,
881 int *retainCount )
882 {
883 if( !object)
884 return( kIOReturnBadArgument );
885
886 *retainCount = object->getRetainCount();
887 return( kIOReturnSuccess );
888 }
889
890 /* Routine io_iterator_next */
891 kern_return_t is_io_iterator_next(
892 io_object_t iterator,
893 io_object_t *object )
894 {
895 OSObject * obj;
896
897 CHECK( OSIterator, iterator, iter );
898
899 obj = iter->getNextObject();
900 if( obj) {
901 obj->retain();
902 *object = obj;
903 return( kIOReturnSuccess );
904 } else
905 return( kIOReturnNoDevice );
906 }
907
908 /* Routine io_iterator_reset */
909 kern_return_t is_io_iterator_reset(
910 io_object_t iterator )
911 {
912 CHECK( OSIterator, iterator, iter );
913
914 iter->reset();
915
916 return( kIOReturnSuccess );
917 }
918
919 /* Routine io_iterator_is_valid */
920 kern_return_t is_io_iterator_is_valid(
921 io_object_t iterator,
922 boolean_t *is_valid )
923 {
924 CHECK( OSIterator, iterator, iter );
925
926 *is_valid = iter->isValid();
927
928 return( kIOReturnSuccess );
929 }
930
931 /* Routine io_service_match_property_table */
932 kern_return_t is_io_service_match_property_table(
933 io_service_t _service,
934 io_string_t matching,
935 boolean_t *matches )
936 {
937 CHECK( IOService, _service, service );
938
939 kern_return_t kr;
940 OSObject * obj;
941 OSDictionary * dict;
942
943 obj = OSUnserializeXML( matching );
944
945 if( (dict = OSDynamicCast( OSDictionary, obj))) {
946 *matches = service->passiveMatch( dict );
947 kr = kIOReturnSuccess;
948 } else
949 kr = kIOReturnBadArgument;
950
951 if( obj)
952 obj->release();
953
954 return( kr );
955 }
956
957 /* Routine io_service_get_matching_services */
958 kern_return_t is_io_service_get_matching_services(
959 mach_port_t master_port,
960 io_string_t matching,
961 io_iterator_t *existing )
962 {
963 kern_return_t kr;
964 OSObject * obj;
965 OSDictionary * dict;
966
967 if( master_port != master_device_port)
968 return( kIOReturnNotPrivileged);
969
970 obj = OSUnserializeXML( matching );
971
972 if( (dict = OSDynamicCast( OSDictionary, obj))) {
973 makeMatchingCompatible( dict ); // temp for binary compatibility
974 *existing = IOService::getMatchingServices( dict );
975 kr = kIOReturnSuccess;
976 } else
977 kr = kIOReturnBadArgument;
978
979 if( obj)
980 obj->release();
981
982 return( kr );
983 }
984
985 /* Routine io_service_add_notification */
986 kern_return_t is_io_service_add_notification(
987 mach_port_t master_port,
988 io_name_t notification_type,
989 io_string_t matching,
990 mach_port_t port,
991 io_async_ref_t reference,
992 mach_msg_type_number_t referenceCnt,
993 io_object_t * notification )
994 {
995
996 IOServiceUserNotification * userNotify = 0;
997 IONotifier * notify = 0;
998 const OSSymbol * sym;
999 OSDictionary * dict;
1000 IOReturn err;
1001 unsigned long int userMsgType;
1002
1003
1004 if( master_port != master_device_port)
1005 return( kIOReturnNotPrivileged);
1006
1007 do {
1008 err = kIOReturnNoResources;
1009
1010 if( !(sym = OSSymbol::withCString( notification_type )))
1011 err = kIOReturnNoResources;
1012
1013 if( !(dict = OSDynamicCast( OSDictionary,
1014 OSUnserializeXML( matching )))) {
1015 err = kIOReturnBadArgument;
1016 continue;
1017 }
1018 makeMatchingCompatible( dict ); // temp for binary compatibility
1019
1020 if( (sym == gIOPublishNotification)
1021 || (sym == gIOFirstPublishNotification))
1022 userMsgType = kIOServicePublishNotificationType;
1023 else if( (sym == gIOMatchedNotification)
1024 || (sym == gIOFirstMatchNotification))
1025 userMsgType = kIOServiceMatchedNotificationType;
1026 else if( sym == gIOTerminatedNotification)
1027 userMsgType = kIOServiceTerminatedNotificationType;
1028 else
1029 userMsgType = kLastIOKitNotificationType;
1030
1031 userNotify = new IOServiceUserNotification;
1032
1033 if( userNotify && !userNotify->init( port, userMsgType,
1034 reference)) {
1035 userNotify->release();
1036 userNotify = 0;
1037 }
1038 if( !userNotify)
1039 continue;
1040
1041 notify = IOService::addNotification( sym, dict,
1042 &userNotify->_handler, userNotify );
1043 if( notify) {
1044 dict = 0;
1045 *notification = userNotify;
1046 userNotify->setNotification( notify );
1047 err = kIOReturnSuccess;
1048 } else
1049 err = kIOReturnUnsupported;
1050
1051 } while( false );
1052
1053 if( sym)
1054 sym->release();
1055 if( dict)
1056 dict->release();
1057
1058 return( err );
1059 }
1060
1061 /* Routine io_service_add_notification_old */
1062 kern_return_t is_io_service_add_notification_old(
1063 mach_port_t master_port,
1064 io_name_t notification_type,
1065 io_string_t matching,
1066 mach_port_t port,
1067 natural_t ref,
1068 io_object_t * notification )
1069 {
1070 return( is_io_service_add_notification( master_port, notification_type,
1071 matching, port, &ref, 1, notification ));
1072 }
1073
1074 /* Routine io_service_add_message_notification */
1075 kern_return_t is_io_service_add_interest_notification(
1076 io_object_t _service,
1077 io_name_t type_of_interest,
1078 mach_port_t port,
1079 io_async_ref_t reference,
1080 mach_msg_type_number_t referenceCnt,
1081 io_object_t * notification )
1082 {
1083
1084 IOServiceMessageUserNotification * userNotify = 0;
1085 IONotifier * notify = 0;
1086 const OSSymbol * sym;
1087 IOReturn err;
1088
1089 CHECK( IOService, _service, service );
1090
1091 err = kIOReturnNoResources;
1092 if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1093
1094 userNotify = new IOServiceMessageUserNotification;
1095
1096 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
1097 reference, kIOUserNotifyMaxMessageSize )) {
1098 userNotify->release();
1099 userNotify = 0;
1100 }
1101 if( !userNotify)
1102 continue;
1103
1104 notify = service->registerInterest( sym,
1105 &userNotify->_handler, userNotify );
1106 if( notify) {
1107 *notification = userNotify;
1108 userNotify->setNotification( notify );
1109 err = kIOReturnSuccess;
1110 } else
1111 err = kIOReturnUnsupported;
1112
1113 } while( false );
1114
1115 return( err );
1116 }
1117
1118 /* Routine io_service_acknowledge_notification */
1119 kern_return_t is_io_service_acknowledge_notification(
1120 io_object_t _service,
1121 natural_t notify_ref,
1122 natural_t response )
1123 {
1124 CHECK( IOService, _service, service );
1125
1126 return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1127 (IOOptionBits) response ));
1128
1129 }
1130
1131 /* Routine io_connect_get_semaphore */
1132 kern_return_t is_io_connect_get_notification_semaphore(
1133 io_connect_t connection,
1134 natural_t notification_type,
1135 semaphore_t *semaphore )
1136 {
1137 CHECK( IOUserClient, connection, client );
1138
1139 return( client->getNotificationSemaphore( (UInt32) notification_type,
1140 semaphore ));
1141 }
1142
1143 /* Routine io_registry_get_root_entry */
1144 kern_return_t is_io_registry_get_root_entry(
1145 mach_port_t master_port,
1146 io_object_t *root )
1147 {
1148 IORegistryEntry * entry;
1149
1150 if( master_port != master_device_port)
1151 return( kIOReturnNotPrivileged);
1152
1153 entry = IORegistryEntry::getRegistryRoot();
1154 if( entry)
1155 entry->retain();
1156 *root = entry;
1157
1158 return( kIOReturnSuccess );
1159 }
1160
1161 /* Routine io_registry_create_iterator */
1162 kern_return_t is_io_registry_create_iterator(
1163 mach_port_t master_port,
1164 io_name_t plane,
1165 int options,
1166 io_object_t *iterator )
1167 {
1168 if( master_port != master_device_port)
1169 return( kIOReturnNotPrivileged);
1170
1171 *iterator = IORegistryIterator::iterateOver(
1172 IORegistryEntry::getPlane( plane ), options );
1173
1174 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1175 }
1176
1177 /* Routine io_registry_entry_create_iterator */
1178 kern_return_t is_io_registry_entry_create_iterator(
1179 io_object_t registry_entry,
1180 io_name_t plane,
1181 int options,
1182 io_object_t *iterator )
1183 {
1184 CHECK( IORegistryEntry, registry_entry, entry );
1185
1186 *iterator = IORegistryIterator::iterateOver( entry,
1187 IORegistryEntry::getPlane( plane ), options );
1188
1189 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1190 }
1191
1192 /* Routine io_registry_iterator_enter */
1193 kern_return_t is_io_registry_iterator_enter_entry(
1194 io_object_t iterator )
1195 {
1196 CHECK( IORegistryIterator, iterator, iter );
1197
1198 iter->enterEntry();
1199
1200 return( kIOReturnSuccess );
1201 }
1202
1203 /* Routine io_registry_iterator_exit */
1204 kern_return_t is_io_registry_iterator_exit_entry(
1205 io_object_t iterator )
1206 {
1207 bool didIt;
1208
1209 CHECK( IORegistryIterator, iterator, iter );
1210
1211 didIt = iter->exitEntry();
1212
1213 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
1214 }
1215
1216 /* Routine io_registry_entry_from_path */
1217 kern_return_t is_io_registry_entry_from_path(
1218 mach_port_t master_port,
1219 io_string_t path,
1220 io_object_t *registry_entry )
1221 {
1222 IORegistryEntry * entry;
1223
1224 if( master_port != master_device_port)
1225 return( kIOReturnNotPrivileged);
1226
1227 entry = IORegistryEntry::fromPath( path );
1228
1229 *registry_entry = entry;
1230
1231 return( kIOReturnSuccess );
1232 }
1233
1234 /* Routine io_registry_entry_in_plane */
1235 kern_return_t is_io_registry_entry_in_plane(
1236 io_object_t registry_entry,
1237 io_name_t plane,
1238 boolean_t *inPlane )
1239 {
1240 CHECK( IORegistryEntry, registry_entry, entry );
1241
1242 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
1243
1244 return( kIOReturnSuccess );
1245 }
1246
1247
1248 /* Routine io_registry_entry_get_path */
1249 kern_return_t is_io_registry_entry_get_path(
1250 io_object_t registry_entry,
1251 io_name_t plane,
1252 io_string_t path )
1253 {
1254 int length;
1255 CHECK( IORegistryEntry, registry_entry, entry );
1256
1257 length = sizeof( io_string_t);
1258 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
1259 return( kIOReturnSuccess );
1260 else
1261 return( kIOReturnBadArgument );
1262 }
1263
1264
1265 /* Routine io_registry_entry_get_name */
1266 kern_return_t is_io_registry_entry_get_name(
1267 io_object_t registry_entry,
1268 io_name_t name )
1269 {
1270 CHECK( IORegistryEntry, registry_entry, entry );
1271
1272 strncpy( name, entry->getName(), sizeof( io_name_t));
1273
1274 return( kIOReturnSuccess );
1275 }
1276
1277 /* Routine io_registry_entry_get_name_in_plane */
1278 kern_return_t is_io_registry_entry_get_name_in_plane(
1279 io_object_t registry_entry,
1280 io_name_t plane,
1281 io_name_t name )
1282 {
1283 CHECK( IORegistryEntry, registry_entry, entry );
1284
1285 strncpy( name, entry->getName( IORegistryEntry::getPlane( plane )),
1286 sizeof( io_name_t));
1287
1288 return( kIOReturnSuccess );
1289 }
1290
1291 // Create a vm_map_copy_t or kalloc'ed data for memory
1292 // to be copied out. ipc will free after the copyout.
1293
1294 static kern_return_t copyoutkdata( void * data, vm_size_t len,
1295 io_buf_ptr_t * buf )
1296 {
1297 kern_return_t err;
1298 vm_map_copy_t copy;
1299
1300 err = vm_map_copyin( kernel_map, (vm_offset_t) data, len,
1301 false /* src_destroy */, &copy);
1302
1303 assert( err == KERN_SUCCESS );
1304 if( err == KERN_SUCCESS )
1305 *buf = (char *) copy;
1306 return( err );
1307 }
1308
1309
1310 /* Routine io_registry_entry_get_properties */
1311 kern_return_t is_io_registry_entry_get_properties(
1312 io_object_t registry_entry,
1313 io_buf_ptr_t *properties,
1314 mach_msg_type_number_t *propertiesCnt )
1315 {
1316 kern_return_t err;
1317 vm_size_t len;
1318
1319 CHECK( IORegistryEntry, registry_entry, entry );
1320
1321 OSSerialize * s = OSSerialize::withCapacity(4096);
1322
1323 if( !s)
1324 return( kIOReturnNoMemory );
1325
1326 s->clearText();
1327
1328 if( entry->serializeProperties( s )) {
1329 len = s->getLength();
1330 *propertiesCnt = len;
1331 err = copyoutkdata( s->text(), len, properties );
1332
1333 } else
1334 err = kIOReturnUnsupported;
1335
1336 s->release();
1337
1338 return( err );
1339 }
1340
1341 /* Routine io_registry_entry_set_properties */
1342 kern_return_t is_io_registry_entry_set_properties
1343 (
1344 io_object_t registry_entry,
1345 io_buf_ptr_t properties,
1346 mach_msg_type_number_t propertiesCnt,
1347 natural_t * result)
1348 {
1349 OSObject * obj;
1350 kern_return_t err;
1351 IOReturn res;
1352 vm_offset_t data;
1353
1354 CHECK( IORegistryEntry, registry_entry, entry );
1355
1356 err = vm_map_copyout( kernel_map, &data, (vm_map_copy_t) properties );
1357
1358 if( KERN_SUCCESS == err) {
1359
1360 // must return success after vm_map_copyout() succeeds
1361 obj = OSUnserializeXML( (const char *) data );
1362 vm_deallocate( kernel_map, data, propertiesCnt );
1363
1364 if( obj) {
1365 res = entry->setProperties( obj );
1366 obj->release();
1367 } else
1368 res = kIOReturnBadArgument;
1369 } else
1370 res = err;
1371
1372 *result = res;
1373 return( err );
1374 }
1375
1376
1377 /* Routine io_registry_entry_get_property */
1378 kern_return_t is_io_registry_entry_get_property(
1379 io_object_t registry_entry,
1380 io_name_t property_name,
1381 io_scalar_inband_t buf,
1382 mach_msg_type_number_t *dataCnt )
1383 {
1384 OSObject * obj;
1385 OSData * data;
1386 OSString * str;
1387 OSBoolean * boo;
1388 OSNumber * off;
1389 UInt64 offsetBytes;
1390 unsigned int len = 0;
1391 const void * bytes = 0;
1392 IOReturn ret = kIOReturnSuccess;
1393
1394 CHECK( IORegistryEntry, registry_entry, entry );
1395
1396 obj = entry->getProperty( property_name );
1397 if( !obj)
1398 return( kIOReturnNoResources );
1399
1400 // One day OSData will be a common container base class
1401 // until then...
1402 if( (data = OSDynamicCast( OSData, obj ))) {
1403 len = data->getLength();
1404 bytes = data->getBytesNoCopy();
1405
1406 } else if( (str = OSDynamicCast( OSString, obj ))) {
1407 len = str->getLength() + 1;
1408 bytes = str->getCStringNoCopy();
1409
1410 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
1411 len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
1412 bytes = boo->isTrue() ? "Yes" : "No";
1413
1414 } else if( (off = OSDynamicCast( OSNumber, obj ))) {
1415 offsetBytes = off->unsigned64BitValue();
1416 len = off->numberOfBytes();
1417 bytes = &offsetBytes;
1418 #if __BIG_ENDIAN__
1419 bytes = (const void *)
1420 (((UInt32) bytes) + (sizeof( UInt64) - len));
1421 #endif
1422
1423 } else
1424 ret = kIOReturnBadArgument;
1425
1426 if( bytes) {
1427 if( *dataCnt < len)
1428 ret = kIOReturnIPCError;
1429 else {
1430 *dataCnt = len;
1431 bcopy( bytes, buf, len );
1432 }
1433 }
1434
1435 return( ret );
1436 }
1437
1438
1439 /* Routine io_registry_entry_get_child_iterator */
1440 kern_return_t is_io_registry_entry_get_child_iterator(
1441 io_object_t registry_entry,
1442 io_name_t plane,
1443 io_object_t *iterator )
1444 {
1445 CHECK( IORegistryEntry, registry_entry, entry );
1446
1447 *iterator = entry->getChildIterator(
1448 IORegistryEntry::getPlane( plane ));
1449
1450 return( kIOReturnSuccess );
1451 }
1452
1453 /* Routine io_registry_entry_get_parent_iterator */
1454 kern_return_t is_io_registry_entry_get_parent_iterator(
1455 io_object_t registry_entry,
1456 io_name_t plane,
1457 io_object_t *iterator)
1458 {
1459 CHECK( IORegistryEntry, registry_entry, entry );
1460
1461 *iterator = entry->getParentIterator(
1462 IORegistryEntry::getPlane( plane ));
1463
1464 return( kIOReturnSuccess );
1465 }
1466
1467 /* Routine io_service_get_busy_state */
1468 kern_return_t is_io_service_get_busy_state(
1469 io_object_t _service,
1470 int *busyState )
1471 {
1472 CHECK( IOService, _service, service );
1473
1474 *busyState = service->getBusyState();
1475
1476 return( kIOReturnSuccess );
1477 }
1478
1479 /* Routine io_service_wait_quiet */
1480 kern_return_t is_io_service_wait_quiet(
1481 io_object_t _service,
1482 mach_timespec_t wait_time )
1483 {
1484 CHECK( IOService, _service, service );
1485
1486 return( service->waitQuiet( &wait_time ));
1487 }
1488
1489 /* Routine io_service_request_probe */
1490 kern_return_t is_io_service_request_probe(
1491 io_object_t _service,
1492 int options )
1493 {
1494 CHECK( IOService, _service, service );
1495
1496 return( service->requestProbe( options ));
1497 }
1498
1499
1500 /* Routine io_service_open */
1501 kern_return_t is_io_service_open(
1502 io_object_t _service,
1503 task_t owningTask,
1504 int connect_type,
1505 io_object_t *connection )
1506 {
1507 IOUserClient * client;
1508 IOReturn err;
1509
1510 CHECK( IOService, _service, service );
1511
1512 err = service->newUserClient( owningTask, (void *) owningTask,
1513 connect_type, &client );
1514
1515 if( err == kIOReturnSuccess) {
1516 assert( OSDynamicCast(IOUserClient, client) );
1517 *connection = client;
1518 }
1519
1520 return( err);
1521 }
1522
1523 /* Routine io_service_close */
1524 kern_return_t is_io_service_close(
1525 io_object_t connection )
1526 {
1527 CHECK( IOUserClient, connection, client );
1528
1529 client->clientClose();
1530
1531 return( kIOReturnSuccess );
1532 }
1533
1534 /* Routine io_connect_get_service */
1535 kern_return_t is_io_connect_get_service(
1536 io_object_t connection,
1537 io_object_t *service )
1538 {
1539 IOService * theService;
1540
1541 CHECK( IOUserClient, connection, client );
1542
1543 theService = client->getService();
1544 if( theService)
1545 theService->retain();
1546
1547 *service = theService;
1548
1549 return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
1550 }
1551
1552 /* Routine io_connect_set_notification_port */
1553 kern_return_t is_io_connect_set_notification_port(
1554 io_object_t connection,
1555 int notification_type,
1556 mach_port_t port,
1557 int reference)
1558 {
1559 CHECK( IOUserClient, connection, client );
1560
1561 return( client->registerNotificationPort( port, notification_type,
1562 reference ));
1563 }
1564
1565 kern_return_t is_io_connect_map_memory(
1566 io_object_t connect,
1567 int type,
1568 task_t task,
1569 vm_address_t * mapAddr,
1570 vm_size_t * mapSize,
1571 int flags )
1572 {
1573 IOReturn err;
1574 IOMemoryMap * map;
1575
1576 CHECK( IOUserClient, connect, client );
1577
1578 map = client->mapClientMemory( type, task, flags, *mapAddr );
1579
1580 if( map) {
1581 *mapAddr = map->getVirtualAddress();
1582 if( mapSize)
1583 *mapSize = map->getLength();
1584
1585 if( task != current_task()) {
1586 // push a name out to the task owning the map,
1587 // so we can clean up maps
1588 mach_port_name_t name = IOMachPort::makeSendRightForTask(
1589 task, map, IKOT_IOKIT_OBJECT );
1590 assert( name );
1591
1592 } else {
1593 // keep it with the user client
1594 IOLockLock( gIOObjectPortLock);
1595 if( 0 == client->mappings)
1596 client->mappings = OSSet::withCapacity(2);
1597 if( client->mappings)
1598 client->mappings->setObject( map);
1599 IOLockUnlock( gIOObjectPortLock);
1600 map->release();
1601 }
1602 err = kIOReturnSuccess;
1603
1604 } else
1605 err = kIOReturnBadArgument;
1606
1607 return( err );
1608 }
1609
1610 kern_return_t is_io_connect_unmap_memory(
1611 io_object_t connect,
1612 int type,
1613 task_t task,
1614 vm_address_t mapAddr )
1615 {
1616 IOReturn err;
1617 IOOptionBits options = 0;
1618 IOMemoryDescriptor * memory;
1619 IOMemoryMap * map;
1620
1621 CHECK( IOUserClient, connect, client );
1622
1623 err = client->clientMemoryForType( (UInt32) type, &options, &memory );
1624
1625 if( memory && (kIOReturnSuccess == err)) {
1626
1627 options = (options & ~kIOMapUserOptionsMask)
1628 | kIOMapAnywhere | kIOMapReference;
1629
1630 map = memory->map( task, mapAddr, options );
1631 memory->release();
1632 if( map) {
1633 IOLockLock( gIOObjectPortLock);
1634 if( client->mappings)
1635 client->mappings->removeObject( map);
1636 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
1637 IOLockUnlock( gIOObjectPortLock);
1638 map->release();
1639 } else
1640 err = kIOReturnBadArgument;
1641 }
1642
1643 return( err );
1644 }
1645
1646
1647 /* Routine io_connect_add_client */
1648 kern_return_t is_io_connect_add_client(
1649 io_object_t connection,
1650 io_object_t connect_to)
1651 {
1652 CHECK( IOUserClient, connection, client );
1653 CHECK( IOUserClient, connect_to, to );
1654
1655 return( client->connectClient( to ) );
1656 }
1657
1658
1659 /* Routine io_connect_set_properties */
1660 kern_return_t is_io_connect_set_properties(
1661 io_object_t connection,
1662 io_buf_ptr_t properties,
1663 mach_msg_type_number_t propertiesCnt,
1664 natural_t * result)
1665 {
1666 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
1667 }
1668
1669
1670 /* Routine io_connect_method_scalarI_scalarO */
1671 kern_return_t is_io_connect_method_scalarI_scalarO(
1672 io_object_t connect,
1673 UInt32 index,
1674 void * input[],
1675 IOByteCount inputCount,
1676 void * output[],
1677 IOByteCount * outputCount )
1678 {
1679 IOReturn err;
1680 IOExternalMethod * method;
1681 IOService * object;
1682 IOMethod func;
1683
1684 CHECK( IOUserClient, connect, client);
1685 if( (method = client->getTargetAndMethodForIndex(&object, index))) {
1686 do {
1687 err = kIOReturnBadArgument;
1688 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
1689 continue;
1690 if( inputCount != method->count0)
1691 continue;
1692 if( *outputCount != method->count1)
1693 continue;
1694
1695 func = method->func;
1696
1697 switch( inputCount) {
1698
1699 case 6:
1700 err = (object->*func)( input[0], input[1], input[2],
1701 input[3], input[4], input[5] );
1702 break;
1703 case 5:
1704 err = (object->*func)( input[0], input[1], input[2],
1705 input[3], input[4],
1706 &output[0] );
1707 break;
1708 case 4:
1709 err = (object->*func)( input[0], input[1], input[2],
1710 input[3],
1711 &output[0], &output[1] );
1712 break;
1713 case 3:
1714 err = (object->*func)( input[0], input[1], input[2],
1715 &output[0], &output[1], &output[2] );
1716 break;
1717 case 2:
1718 err = (object->*func)( input[0], input[1],
1719 &output[0], &output[1], &output[2],
1720 &output[3] );
1721 break;
1722 case 1:
1723 err = (object->*func)( input[0],
1724 &output[0], &output[1], &output[2],
1725 &output[3], &output[4] );
1726 break;
1727 case 0:
1728 err = (object->*func)( &output[0], &output[1], &output[2],
1729 &output[3], &output[4], &output[5] );
1730 break;
1731
1732 default:
1733 IOLog("%s: Bad method table\n", client->getName());
1734 }
1735 } while( false);
1736
1737 } else
1738 err = kIOReturnUnsupported;
1739
1740 return( err);
1741 }
1742
1743 /* Routine io_connect_method_scalarI_structureO */
1744 kern_return_t is_io_connect_method_scalarI_structureO(
1745 io_object_t connect,
1746 UInt32 index,
1747 void * input[],
1748 IOByteCount inputCount,
1749 void * output,
1750 IOByteCount * outputCount )
1751 {
1752 IOReturn err;
1753 IOExternalMethod * method;
1754 IOService * object;
1755 IOMethod func;
1756
1757 CHECK( IOUserClient, connect, client);
1758
1759 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
1760 do {
1761 err = kIOReturnBadArgument;
1762 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
1763 continue;
1764 if( inputCount != method->count0)
1765 continue;
1766 if( (0xffffffff != method->count1)
1767 && (*outputCount != method->count1))
1768 continue;
1769
1770 func = method->func;
1771
1772 switch( inputCount) {
1773
1774 case 5:
1775 err = (object->*func)( input[0], input[1], input[2],
1776 input[3], input[4],
1777 output );
1778 break;
1779 case 4:
1780 err = (object->*func)( input[0], input[1], input[2],
1781 input[3],
1782 output, (void *)outputCount );
1783 break;
1784 case 3:
1785 err = (object->*func)( input[0], input[1], input[2],
1786 output, (void *)outputCount, 0 );
1787 break;
1788 case 2:
1789 err = (object->*func)( input[0], input[1],
1790 output, (void *)outputCount, 0, 0 );
1791 break;
1792 case 1:
1793 err = (object->*func)( input[0],
1794 output, (void *)outputCount, 0, 0, 0 );
1795 break;
1796 case 0:
1797 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 );
1798 break;
1799
1800 default:
1801 IOLog("%s: Bad method table\n", client->getName());
1802 }
1803 } while( false);
1804
1805 } else
1806 err = kIOReturnUnsupported;
1807
1808 return( err);
1809 }
1810
1811 /* Routine io_connect_method_scalarI_structureI */
1812 kern_return_t is_io_connect_method_scalarI_structureI(
1813 io_connect_t connect,
1814 UInt32 index,
1815 void * input[],
1816 IOByteCount inputCount,
1817 UInt8 * inputStruct,
1818 IOByteCount inputStructCount )
1819 {
1820 IOReturn err;
1821 IOExternalMethod * method;
1822 IOService * object;
1823 IOMethod func;
1824
1825 CHECK( IOUserClient, connect, client);
1826
1827 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
1828 do {
1829 err = kIOReturnBadArgument;
1830 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
1831 continue;
1832 if( (0xffffffff != method->count0)
1833 && (inputCount != method->count0))
1834 continue;
1835 if( (0xffffffff != method->count1)
1836 && (inputStructCount != method->count1))
1837 continue;
1838
1839 func = method->func;
1840
1841 switch( inputCount) {
1842
1843 case 5:
1844 err = (object->*func)( input[0], input[1], input[2],
1845 input[3], input[4],
1846 inputStruct );
1847 break;
1848 case 4:
1849 err = (object->*func)( input[0], input[1], input[2],
1850 input[3],
1851 inputStruct, (void *)inputStructCount );
1852 break;
1853 case 3:
1854 err = (object->*func)( input[0], input[1], input[2],
1855 inputStruct, (void *)inputStructCount,
1856 0 );
1857 break;
1858 case 2:
1859 err = (object->*func)( input[0], input[1],
1860 inputStruct, (void *)inputStructCount,
1861 0, 0 );
1862 break;
1863 case 1:
1864 err = (object->*func)( input[0],
1865 inputStruct, (void *)inputStructCount,
1866 0, 0, 0 );
1867 break;
1868 case 0:
1869 err = (object->*func)( inputStruct, (void *)inputStructCount,
1870 0, 0, 0, 0 );
1871 break;
1872
1873 default:
1874 IOLog("%s: Bad method table\n", client->getName());
1875 }
1876 } while( false);
1877
1878 } else
1879 err = kIOReturnUnsupported;
1880
1881 return( err);
1882 }
1883
1884 /* Routine io_connect_method_structureI_structureO */
1885 kern_return_t is_io_connect_method_structureI_structureO(
1886 io_object_t connect,
1887 UInt32 index,
1888 UInt8 * input,
1889 IOByteCount inputCount,
1890 UInt8 * output,
1891 IOByteCount * outputCount )
1892 {
1893 IOReturn err;
1894 IOExternalMethod * method;
1895 IOService * object;
1896 IOMethod func;
1897
1898 CHECK( IOUserClient, connect, client);
1899
1900 if( (method = client->getTargetAndMethodForIndex(&object, index)) ) {
1901 do {
1902 err = kIOReturnBadArgument;
1903 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
1904 continue;
1905 if( (0xffffffff != method->count0)
1906 && (inputCount != method->count0))
1907 continue;
1908 if( (0xffffffff != method->count1)
1909 && (*outputCount != method->count1))
1910 continue;
1911
1912 func = method->func;
1913
1914 if( method->count1) {
1915 if( method->count0) {
1916 err = (object->*func)( input, output,
1917 (void *)inputCount, outputCount, 0, 0 );
1918 } else {
1919 err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
1920 }
1921 } else {
1922 err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
1923 }
1924
1925 } while( false);
1926
1927 } else
1928 err = kIOReturnUnsupported;
1929
1930 return( err);
1931 }
1932
1933 kern_return_t is_io_async_method_scalarI_scalarO(
1934 io_object_t connect,
1935 mach_port_t wakePort,
1936 io_async_ref_t reference,
1937 mach_msg_type_number_t referenceCnt,
1938 UInt32 index,
1939 void * input[],
1940 IOByteCount inputCount,
1941 void * output[],
1942 IOByteCount * outputCount )
1943 {
1944 IOReturn err;
1945 IOExternalAsyncMethod *method;
1946 IOService * object;
1947 IOAsyncMethod func;
1948
1949 CHECK( IOUserClient, connect, client);
1950 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
1951 do {
1952 err = kIOReturnBadArgument;
1953 if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
1954 continue;
1955 if( inputCount != method->count0)
1956 continue;
1957 if( *outputCount != method->count1)
1958 continue;
1959
1960 reference[0] = (natural_t) wakePort;
1961 func = method->func;
1962
1963 switch( inputCount) {
1964
1965 case 6:
1966 err = (object->*func)( reference,
1967 input[0], input[1], input[2],
1968 input[3], input[4], input[5] );
1969 break;
1970 case 5:
1971 err = (object->*func)( reference,
1972 input[0], input[1], input[2],
1973 input[3], input[4],
1974 &output[0] );
1975 break;
1976 case 4:
1977 err = (object->*func)( reference,
1978 input[0], input[1], input[2],
1979 input[3],
1980 &output[0], &output[1] );
1981 break;
1982 case 3:
1983 err = (object->*func)( reference,
1984 input[0], input[1], input[2],
1985 &output[0], &output[1], &output[2] );
1986 break;
1987 case 2:
1988 err = (object->*func)( reference,
1989 input[0], input[1],
1990 &output[0], &output[1], &output[2],
1991 &output[3] );
1992 break;
1993 case 1:
1994 err = (object->*func)( reference,
1995 input[0],
1996 &output[0], &output[1], &output[2],
1997 &output[3], &output[4] );
1998 break;
1999 case 0:
2000 err = (object->*func)( reference,
2001 &output[0], &output[1], &output[2],
2002 &output[3], &output[4], &output[5] );
2003 break;
2004
2005 default:
2006 IOLog("%s: Bad method table\n", client->getName());
2007 }
2008 } while( false);
2009
2010 } else
2011 err = kIOReturnUnsupported;
2012
2013 return( err);
2014 }
2015
2016 kern_return_t is_io_async_method_scalarI_structureO(
2017 io_object_t connect,
2018 mach_port_t wakePort,
2019 io_async_ref_t reference,
2020 mach_msg_type_number_t referenceCnt,
2021 UInt32 index,
2022 void * input[],
2023 IOByteCount inputCount,
2024 void * output,
2025 IOByteCount * outputCount )
2026 {
2027 IOReturn err;
2028 IOExternalAsyncMethod *method;
2029 IOService * object;
2030 IOAsyncMethod func;
2031
2032 CHECK( IOUserClient, connect, client);
2033
2034 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2035 do {
2036 err = kIOReturnBadArgument;
2037 if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
2038 continue;
2039 if( inputCount != method->count0)
2040 continue;
2041 if( (0xffffffff != method->count1)
2042 && (*outputCount != method->count1))
2043 continue;
2044
2045 reference[0] = (natural_t) wakePort;
2046 func = method->func;
2047
2048 switch( inputCount) {
2049
2050 case 5:
2051 err = (object->*func)( reference,
2052 input[0], input[1], input[2],
2053 input[3], input[4],
2054 output );
2055 break;
2056 case 4:
2057 err = (object->*func)( reference,
2058 input[0], input[1], input[2],
2059 input[3],
2060 output, (void *)outputCount );
2061 break;
2062 case 3:
2063 err = (object->*func)( reference,
2064 input[0], input[1], input[2],
2065 output, (void *)outputCount, 0 );
2066 break;
2067 case 2:
2068 err = (object->*func)( reference,
2069 input[0], input[1],
2070 output, (void *)outputCount, 0, 0 );
2071 break;
2072 case 1:
2073 err = (object->*func)( reference,
2074 input[0],
2075 output, (void *)outputCount, 0, 0, 0 );
2076 break;
2077 case 0:
2078 err = (object->*func)( reference,
2079 output, (void *)outputCount, 0, 0, 0, 0 );
2080 break;
2081
2082 default:
2083 IOLog("%s: Bad method table\n", client->getName());
2084 }
2085 } while( false);
2086
2087 } else
2088 err = kIOReturnUnsupported;
2089
2090 return( err);
2091 }
2092
2093 kern_return_t is_io_async_method_scalarI_structureI(
2094 io_connect_t connect,
2095 mach_port_t wakePort,
2096 io_async_ref_t reference,
2097 mach_msg_type_number_t referenceCnt,
2098 UInt32 index,
2099 void * input[],
2100 IOByteCount inputCount,
2101 UInt8 * inputStruct,
2102 IOByteCount inputStructCount )
2103 {
2104 IOReturn err;
2105 IOExternalAsyncMethod *method;
2106 IOService * object;
2107 IOAsyncMethod func;
2108
2109 CHECK( IOUserClient, connect, client);
2110
2111 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2112 do {
2113 err = kIOReturnBadArgument;
2114 if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
2115 continue;
2116 if( (0xffffffff != method->count0)
2117 && (inputCount != method->count0))
2118 continue;
2119 if( (0xffffffff != method->count1)
2120 && (inputStructCount != method->count1))
2121 continue;
2122
2123 reference[0] = (natural_t) wakePort;
2124 func = method->func;
2125
2126 switch( inputCount) {
2127
2128 case 5:
2129 err = (object->*func)( reference,
2130 input[0], input[1], input[2],
2131 input[3], input[4],
2132 inputStruct );
2133 break;
2134 case 4:
2135 err = (object->*func)( reference,
2136 input[0], input[1], input[2],
2137 input[3],
2138 inputStruct, (void *)inputStructCount );
2139 break;
2140 case 3:
2141 err = (object->*func)( reference,
2142 input[0], input[1], input[2],
2143 inputStruct, (void *)inputStructCount,
2144 0 );
2145 break;
2146 case 2:
2147 err = (object->*func)( reference,
2148 input[0], input[1],
2149 inputStruct, (void *)inputStructCount,
2150 0, 0 );
2151 break;
2152 case 1:
2153 err = (object->*func)( reference,
2154 input[0],
2155 inputStruct, (void *)inputStructCount,
2156 0, 0, 0 );
2157 break;
2158 case 0:
2159 err = (object->*func)( reference,
2160 inputStruct, (void *)inputStructCount,
2161 0, 0, 0, 0 );
2162 break;
2163
2164 default:
2165 IOLog("%s: Bad method table\n", client->getName());
2166 }
2167 } while( false);
2168
2169 } else
2170 err = kIOReturnUnsupported;
2171
2172 return( err);
2173 }
2174
2175 kern_return_t is_io_async_method_structureI_structureO(
2176 io_object_t connect,
2177 mach_port_t wakePort,
2178 io_async_ref_t reference,
2179 mach_msg_type_number_t referenceCnt,
2180 UInt32 index,
2181 UInt8 * input,
2182 IOByteCount inputCount,
2183 UInt8 * output,
2184 IOByteCount * outputCount )
2185 {
2186 IOReturn err;
2187 IOExternalAsyncMethod *method;
2188 IOService * object;
2189 IOAsyncMethod func;
2190
2191 CHECK( IOUserClient, connect, client);
2192
2193 if( (method = client->getAsyncTargetAndMethodForIndex(&object, index)) ) {
2194 do {
2195 err = kIOReturnBadArgument;
2196 if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
2197 continue;
2198 if( (0xffffffff != method->count0)
2199 && (inputCount != method->count0))
2200 continue;
2201 if( (0xffffffff != method->count1)
2202 && (*outputCount != method->count1))
2203 continue;
2204
2205 reference[0] = (natural_t) wakePort;
2206 func = method->func;
2207
2208 if( method->count1) {
2209 if( method->count0) {
2210 err = (object->*func)( reference,
2211 input, output,
2212 (void *)inputCount, outputCount, 0, 0 );
2213 } else {
2214 err = (object->*func)( reference,
2215 output, outputCount, 0, 0, 0, 0 );
2216 }
2217 } else {
2218 err = (object->*func)( reference,
2219 input, (void *)inputCount, 0, 0, 0, 0 );
2220 }
2221
2222 } while( false);
2223
2224 } else
2225 err = kIOReturnUnsupported;
2226
2227 return( err);
2228 }
2229 /* Routine io_make_matching */
2230 kern_return_t is_io_make_matching(
2231 mach_port_t master_port,
2232 UInt32 type,
2233 IOOptionBits options,
2234 UInt8 * input,
2235 IOByteCount inputCount,
2236 io_string_t matching )
2237 {
2238 OSSerialize * s;
2239 IOReturn err = kIOReturnSuccess;
2240 OSDictionary * dict;
2241
2242 if( master_port != master_device_port)
2243 return( kIOReturnNotPrivileged);
2244
2245 switch( type) {
2246
2247 case kIOServiceMatching:
2248 dict = IOService::serviceMatching( gIOServiceKey );
2249 break;
2250
2251 case kIOBSDNameMatching:
2252 dict = IOBSDNameMatching( (const char *) input );
2253 break;
2254
2255 case kIOOFPathMatching:
2256 dict = IOOFPathMatching( (const char *) input,
2257 matching, sizeof( io_string_t));
2258 break;
2259
2260 default:
2261 dict = 0;
2262 }
2263
2264 if( !dict)
2265 return( kIOReturnUnsupported);
2266
2267 do {
2268 s = OSSerialize::withCapacity(4096);
2269 if( !s) {
2270 err = kIOReturnNoMemory;
2271 continue;
2272 }
2273 s->clearText();
2274 if( !dict->serialize( s )) {
2275 err = kIOReturnUnsupported;
2276 continue;
2277 }
2278
2279 if( s->getLength() > sizeof( io_string_t)) {
2280 err = kIOReturnNoMemory;
2281 continue;
2282 } else
2283 strcpy( matching, s->text());
2284
2285 } while( false);
2286
2287 if( s)
2288 s->release();
2289 if( dict)
2290 dict->release();
2291
2292 return( err);
2293 }
2294
2295 /* Routine io_catalog_send_data */
2296 kern_return_t is_io_catalog_send_data(
2297 mach_port_t master_port,
2298 int flag,
2299 io_buf_ptr_t inData,
2300 mach_msg_type_number_t inDataCount,
2301 natural_t * result)
2302 {
2303 OSObject * obj = 0;
2304 vm_offset_t data;
2305 kern_return_t kr = kIOReturnError;
2306
2307 //printf("io_catalog_send_data called. flag: %d\n", flag);
2308
2309 if( master_port != master_device_port)
2310 return kIOReturnNotPrivileged;
2311
2312 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2313 if(flag != kIOCatalogRemoveKernelLinker && ( !inData || !inDataCount) )
2314 return kIOReturnBadArgument;
2315
2316 if (data) {
2317 kr = vm_map_copyout( kernel_map, &data, (vm_map_copy_t)inData);
2318 if( kr != KERN_SUCCESS)
2319 return kr;
2320
2321 // must return success after vm_map_copyout() succeeds
2322
2323 if( inDataCount ) {
2324 obj = (OSObject *)OSUnserializeXML((const char *)data);
2325 vm_deallocate( kernel_map, data, inDataCount );
2326 if( !obj) {
2327 *result = kIOReturnNoMemory;
2328 return( KERN_SUCCESS);
2329 }
2330 }
2331 }
2332
2333 switch ( flag ) {
2334 case kIOCatalogAddDrivers:
2335 case kIOCatalogAddDriversNoMatch: {
2336 OSArray * array;
2337
2338 array = OSDynamicCast(OSArray, obj);
2339 if ( array ) {
2340 //--
2341 OSDictionary * dict;
2342 int i = 0;
2343 while( (dict = OSDynamicCast(OSDictionary, array->getObject(i++))))
2344 makeMatchingCompatible( dict );
2345 //--
2346 if ( !gIOCatalogue->addDrivers( array ,
2347 flag == kIOCatalogAddDrivers) ) {
2348 kr = kIOReturnError;
2349 }
2350 }
2351 else {
2352 kr = kIOReturnBadArgument;
2353 }
2354 }
2355 break;
2356
2357 case kIOCatalogRemoveDrivers:
2358 case kIOCatalogRemoveDriversNoMatch: {
2359 OSDictionary * dict;
2360
2361 dict = OSDynamicCast(OSDictionary, obj);
2362 if ( dict ) {
2363 makeMatchingCompatible( dict );
2364 if ( !gIOCatalogue->removeDrivers( dict,
2365 flag == kIOCatalogRemoveDrivers ) ) {
2366 kr = kIOReturnError;
2367 }
2368 }
2369 else {
2370 kr = kIOReturnBadArgument;
2371 }
2372 }
2373 break;
2374
2375 case kIOCatalogStartMatching: {
2376 OSDictionary * dict;
2377
2378 dict = OSDynamicCast(OSDictionary, obj);
2379 if ( dict ) {
2380 makeMatchingCompatible( dict );
2381 if ( !gIOCatalogue->startMatching( dict ) ) {
2382 kr = kIOReturnError;
2383 }
2384 }
2385 else {
2386 kr = kIOReturnBadArgument;
2387 }
2388 }
2389 break;
2390
2391 case kIOCatalogRemoveKernelLinker: {
2392 if (gIOCatalogue->removeKernelLinker() != KERN_SUCCESS) {
2393 kr = kIOReturnError;
2394 }
2395 }
2396 break;
2397
2398 default:
2399 kr = kIOReturnBadArgument;
2400 break;
2401 }
2402
2403 if (obj) obj->release();
2404
2405 *result = kr;
2406 return( KERN_SUCCESS);
2407 }
2408
2409 /* Routine io_catalog_terminate */
2410 kern_return_t is_io_catalog_terminate(
2411 mach_port_t master_port,
2412 int flag,
2413 io_name_t name )
2414 {
2415 kern_return_t kr;
2416
2417 if( master_port != master_device_port )
2418 return kIOReturnNotPrivileged;
2419
2420 kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
2421 kIOClientPrivilegeAdministrator );
2422 if( kIOReturnSuccess != kr)
2423 return( kr );
2424
2425 switch ( flag ) {
2426 case kIOCatalogServiceTerminate:
2427 OSIterator * iter;
2428 IOService * service;
2429
2430 iter = IORegistryIterator::iterateOver(gIOServicePlane,
2431 kIORegistryIterateRecursively);
2432 if ( !iter )
2433 return kIOReturnNoMemory;
2434
2435 do {
2436 iter->reset();
2437 while( (service = (IOService *)iter->getNextObject()) ) {
2438 if( service->metaCast(name)) {
2439 if ( !service->terminate( kIOServiceRequired
2440 | kIOServiceSynchronous) ) {
2441 kr = kIOReturnUnsupported;
2442 break;
2443 }
2444 }
2445 }
2446 } while( !service && !iter->isValid());
2447 iter->release();
2448 break;
2449
2450 case kIOCatalogModuleUnload:
2451 case kIOCatalogModuleTerminate:
2452 kr = gIOCatalogue->terminateDriversForModule(name,
2453 flag == kIOCatalogModuleUnload);
2454 break;
2455
2456 default:
2457 kr = kIOReturnBadArgument;
2458 break;
2459 }
2460
2461 return( kr );
2462 }
2463
2464 /* Routine io_catalog_get_data */
2465 kern_return_t is_io_catalog_get_data(
2466 mach_port_t master_port,
2467 int flag,
2468 io_buf_ptr_t *outData,
2469 mach_msg_type_number_t *outDataCount)
2470 {
2471 kern_return_t kr = kIOReturnSuccess;
2472 OSSerialize * s;
2473
2474 if( master_port != master_device_port)
2475 return kIOReturnNotPrivileged;
2476
2477 //printf("io_catalog_get_data called. flag: %d\n", flag);
2478
2479 s = OSSerialize::withCapacity(4096);
2480 if ( !s )
2481 return kIOReturnNoMemory;
2482
2483 s->clearText();
2484 switch ( flag ) {
2485 case kIOCatalogGetContents:
2486 if ( !gIOCatalogue->serialize(s) ) {
2487 kr = kIOReturnNoMemory;
2488 }
2489 break;
2490
2491 default:
2492 kr = kIOReturnBadArgument;
2493 break;
2494 }
2495
2496 if ( kr == kIOReturnSuccess ) {
2497 vm_offset_t data;
2498 vm_map_copy_t copy;
2499 vm_size_t size;
2500
2501 size = s->getLength();
2502 kr = vm_allocate(kernel_map, &data, size, true);
2503 if ( kr == kIOReturnSuccess ) {
2504 bcopy(s->text(), (void *)data, size);
2505 kr = vm_map_copyin(kernel_map, data, size, true, &copy);
2506 *outData = (char *)copy;
2507 *outDataCount = size;
2508 }
2509 }
2510
2511 s->release();
2512
2513 return kr;
2514 }
2515
2516 /* Routine io_catalog_get_gen_count */
2517 kern_return_t is_io_catalog_get_gen_count(
2518 mach_port_t master_port,
2519 int *genCount)
2520 {
2521 if( master_port != master_device_port)
2522 return kIOReturnNotPrivileged;
2523
2524 //printf("io_catalog_get_gen_count called.\n");
2525
2526 if ( !genCount )
2527 return kIOReturnBadArgument;
2528
2529 *genCount = gIOCatalogue->getGenerationCount();
2530
2531 return kIOReturnSuccess;
2532 }
2533
2534 /* Routine io_catalog_module_loaded */
2535 kern_return_t is_io_catalog_module_loaded(
2536 mach_port_t master_port,
2537 io_name_t name)
2538 {
2539 if( master_port != master_device_port)
2540 return kIOReturnNotPrivileged;
2541
2542 //printf("io_catalog_module_loaded called. name %s\n", name);
2543
2544 if ( !name )
2545 return kIOReturnBadArgument;
2546
2547 gIOCatalogue->moduleHasLoaded(name);
2548
2549 return kIOReturnSuccess;
2550 }
2551
2552 kern_return_t is_io_catalog_reset(
2553 mach_port_t master_port,
2554 int flag)
2555 {
2556 if( master_port != master_device_port)
2557 return kIOReturnNotPrivileged;
2558
2559 switch ( flag ) {
2560 case kIOCatalogResetDefault:
2561 gIOCatalogue->reset();
2562 break;
2563
2564 default:
2565 return kIOReturnBadArgument;
2566 }
2567
2568 return kIOReturnSuccess;
2569 }
2570
2571 kern_return_t iokit_user_client_trap(io_object_t userClientRef, UInt32 index, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6)
2572 {
2573 kern_return_t result = kIOReturnBadArgument;
2574 IOUserClient *userClient;
2575
2576 if ((userClient = OSDynamicCast(IOUserClient, iokit_lookup_connect_ref_current_task(userClientRef)))) {
2577 IOExternalTrap *trap;
2578 IOService *target = NULL;
2579
2580 trap = userClient->getTargetAndTrapForIndex(&target, index);
2581
2582 if (trap && target) {
2583 IOTrap func;
2584
2585 func = trap->func;
2586
2587 if (func) {
2588 result = (target->*func)(p1, p2, p3, p4, p5, p6);
2589 }
2590 }
2591
2592 userClient->release();
2593 }
2594
2595 return result;
2596 }
2597
2598 }; /* extern "C" */
2599
2600 OSMetaClassDefineReservedUnused(IOUserClient, 0);
2601 OSMetaClassDefineReservedUnused(IOUserClient, 1);
2602 OSMetaClassDefineReservedUnused(IOUserClient, 2);
2603 OSMetaClassDefineReservedUnused(IOUserClient, 3);
2604 OSMetaClassDefineReservedUnused(IOUserClient, 4);
2605 OSMetaClassDefineReservedUnused(IOUserClient, 5);
2606 OSMetaClassDefineReservedUnused(IOUserClient, 6);
2607 OSMetaClassDefineReservedUnused(IOUserClient, 7);
2608 OSMetaClassDefineReservedUnused(IOUserClient, 8);
2609 OSMetaClassDefineReservedUnused(IOUserClient, 9);
2610 OSMetaClassDefineReservedUnused(IOUserClient, 10);
2611 OSMetaClassDefineReservedUnused(IOUserClient, 11);
2612 OSMetaClassDefineReservedUnused(IOUserClient, 12);
2613 OSMetaClassDefineReservedUnused(IOUserClient, 13);
2614 OSMetaClassDefineReservedUnused(IOUserClient, 14);
2615 OSMetaClassDefineReservedUnused(IOUserClient, 15);
2616