]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOUserClient.cpp
xnu-201.42.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
CommitLineData
1c79356b
A
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;
46typedef 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
52extern "C" {
53
54extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
55 ipc_kobject_type_t type );
56
57extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
58
59extern mach_port_name_t iokit_make_send_right( task_t task,
60 io_object_t obj, ipc_kobject_type_t type );
61
62extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
63
64extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
65
66extern 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
77class IOMachPort : public OSObject
78{
79 OSDeclareDefaultStructors(IOMachPort)
80public:
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
97OSDefineMetaClassAndStructors(IOMachPort, OSObject)
98
99static IOLock * gIOObjectPortLock;
100
101/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102
103// not in dictForType() for debugging ease
104static OSDictionary * gIOObjectPorts;
105static OSDictionary * gIOConnectPorts;
106
107OSDictionary * 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
124IOMachPort * 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
166void 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
182void IOUserClient::destroyUserReferences( OSObject * obj )
183{
184 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
185 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
186}
187
188mach_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
194void IOMachPort::free( void )
195{
196 if( port)
197 iokit_destroy_object_port( port );
198 super::free();
199}
200
201/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
202
203extern "C" {
204
205// functions called from osfmk/device/iokit_rpc.c
206
207void
208iokit_add_reference( io_object_t obj )
209{
210 if( obj)
211 obj->retain();
212}
213
214void
215iokit_remove_reference( io_object_t obj )
216{
217 if( obj)
218 obj->release();
219}
220
221ipc_port_t
222iokit_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
232kern_return_t
233iokit_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
255class 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
269public:
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
282class IOServiceUserNotification : public IOUserNotification
283{
284 OSDeclareDefaultStructors(IOServiceUserNotification)
285
286 enum { kMaxOutstanding = 256 };
287
288 OSArray * newSet;
289 OSObject * lastEntry;
290 bool armed;
291
292public:
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
305class IOServiceMessageUserNotification : public IOUserNotification
306{
307 OSDeclareDefaultStructors(IOServiceMessageUserNotification)
308
309public:
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
329OSDefineMetaClass( IOUserNotification, OSIterator )
330OSDefineAbstractStructors( IOUserNotification, OSIterator )
331
332/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
333
334bool 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
365void 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
381void IOUserNotification::setNotification( IONotifier * notify )
382{
383 if( holdNotify)
384 holdNotify->remove();
385
386 holdNotify = notify;
387}
388
389void IOUserNotification::reset()
390{
391 // ?
392}
393
394bool IOUserNotification::isValid()
395{
396 return( true );
397}
398
399/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
400
401#undef super
402#define super IOUserNotification
403OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
404
405/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
406
407bool 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
417void IOServiceUserNotification::free( void )
418{
419 if( lastEntry)
420 lastEntry->release();
421
422 if( newSet)
423 newSet->release();
424
425 super::free();
426}
427
428bool IOServiceUserNotification::_handler( void * target,
429 void * ref, IOService * newService )
430{
431 return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
432}
433
434bool 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
468OSObject * 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
496OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
497
498/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
499
500bool 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
507void IOServiceMessageUserNotification::free( void )
508{
509 super::free();
510}
511
512IOReturn 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
520IOReturn 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
556OSObject * IOServiceMessageUserNotification::getNextObject()
557{
558 return( 0 );
559}
560
561/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
562
563#undef super
564#define super IOService
565OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
566
567void IOUserClient::initialize( void )
568{
569 gIOObjectPortLock = IOLockAlloc();
570
571 assert( gIOObjectPortLock );
572}
573
574void 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
583IOReturn 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
603bool 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
613bool 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
626void IOUserClient::free()
627{
628 if( mappings)
629 mappings->release();
630
631 super::free();
632}
633
634IOReturn IOUserClient::clientDied( void )
635{
636 return( clientClose());
637}
638
639IOReturn IOUserClient::clientClose( void )
640{
641 return( kIOReturnUnsupported );
642}
643
644IOService * IOUserClient::getService( void )
645{
646 return( 0 );
647}
648
649IOReturn IOUserClient::registerNotificationPort(
650 mach_port_t /* port */,
651 UInt32 /* type */,
652 UInt32 /* refCon */)
653{
654 return( kIOReturnUnsupported);
655}
656
657IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
658 semaphore_t * semaphore )
659{
660 return( kIOReturnUnsupported);
661}
662
663IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
664{
665 return( kIOReturnUnsupported);
666}
667
668IOReturn IOUserClient::clientMemoryForType( UInt32 type,
669 IOOptionBits * options,
670 IOMemoryDescriptor ** memory )
671{
672 return( kIOReturnUnsupported);
673}
674
675IOMemoryMap * 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
699IOReturn 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
711IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
712{
713 return( 0 );
714}
715
716IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
717{
718 return( 0 );
719}
720
721IOExternalMethod * IOUserClient::
722getTargetAndMethodForIndex(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
732IOExternalAsyncMethod * IOUserClient::
733getAsyncTargetAndMethodForIndex(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
743IOExternalTrap * IOUserClient::
744getExternalTrapForIndex(UInt32 index)
745{
746 return NULL;
747}
748
749IOExternalTrap * IOUserClient::
750getTargetAndTrapForIndex(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
761IOReturn 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
1c79356b
A
805extern "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 */
813kern_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 */
825kern_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 */
838kern_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 */
850kern_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 */
868kern_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 */
879kern_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 */
891kern_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 */
917kern_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))) {
1c79356b
A
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 */
944kern_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 }
1c79356b
A
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 */
1019kern_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 */
1032kern_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 */
1076kern_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 */
1089kern_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 */
1101kern_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 */
1119kern_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 */
1135kern_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 */
1150kern_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 */
1161kern_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 */
1174kern_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 */
1192kern_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 */
1206kern_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 */
1223kern_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 */
1235kern_return_t is_io_registry_entry_get_name_in_plane(
1236 io_object_t registry_entry,
0b4e3aa0 1237 io_name_t planeName,
1c79356b
A
1238 io_name_t name )
1239{
0b4e3aa0 1240 const IORegistryPlane * plane;
1c79356b
A
1241 CHECK( IORegistryEntry, registry_entry, entry );
1242
0b4e3aa0
A
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));
1c79356b
A
1249
1250 return( kIOReturnSuccess );
1251}
1252
0b4e3aa0
A
1253/* Routine io_registry_entry_get_location_in_plane */
1254kern_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
1c79356b
A
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
1279static 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
0b4e3aa0
A
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 */
1296kern_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 */
1365kern_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();
1c79356b 1405
1c79356b
A
1406 return( err );
1407}
1408
0b4e3aa0
A
1409/* Routine io_registry_entry_get_property_recursively */
1410kern_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}
1c79356b
A
1457
1458/* Routine io_registry_entry_get_properties */
1459kern_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);
1c79356b
A
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
0b4e3aa0 1483 s->release();
1c79356b
A
1484
1485 return( err );
1486}
1487
1488/* Routine io_registry_entry_set_properties */
1489kern_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
1c79356b
A
1523/* Routine io_registry_entry_get_child_iterator */
1524kern_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 */
1538kern_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 */
1552kern_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 */
1564kern_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 */
1574kern_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 */
1585kern_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 */
1608kern_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 */
1619kern_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 */
1637kern_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
1649kern_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
1694kern_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);
1c79356b 1720 IOLockUnlock( gIOObjectPortLock);
0b4e3aa0 1721 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
1c79356b
A
1722 map->release();
1723 } else
1724 err = kIOReturnBadArgument;
1725 }
1726
1727 return( err );
1728}
1729
1730
1731/* Routine io_connect_add_client */
1732kern_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 */
1744kern_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 */
1755kern_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 */
1828kern_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 */
1896kern_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 */
1969kern_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
2017kern_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
2100kern_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
2177kern_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
2259kern_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 */
2314kern_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 */
2380kern_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 ) {
1c79356b
A
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 ) {
1c79356b
A
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 ) {
1c79356b
A
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 */
2486kern_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 */
2541kern_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 */
2593kern_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 */
2611kern_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
2628kern_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
0b4e3aa0
A
2647kern_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)
1c79356b 2650{
0b4e3aa0
A
2651 kern_return_t result = kIOReturnBadArgument;
2652 IOUserClient *userClient;
1c79356b 2653
0b4e3aa0
A
2654 if ((userClient = OSDynamicCast(IOUserClient,
2655 iokit_lookup_connect_ref_current_task(userClientRef)))) {
2656 IOExternalTrap *trap;
2657 IOService *target = NULL;
1c79356b 2658
0b4e3aa0 2659 trap = userClient->getTargetAndTrapForIndex(&target, index);
1c79356b 2660
0b4e3aa0
A
2661 if (trap && target) {
2662 IOTrap func;
1c79356b 2663
0b4e3aa0 2664 func = trap->func;
1c79356b 2665
0b4e3aa0
A
2666 if (func) {
2667 result = (target->*func)(p1, p2, p3, p4, p5, p6);
2668 }
2669 }
1c79356b 2670
0b4e3aa0
A
2671 userClient->release();
2672 }
1c79356b 2673
0b4e3aa0 2674 return result;
1c79356b
A
2675}
2676
2677}; /* extern "C" */
2678
2679OSMetaClassDefineReservedUnused(IOUserClient, 0);
2680OSMetaClassDefineReservedUnused(IOUserClient, 1);
2681OSMetaClassDefineReservedUnused(IOUserClient, 2);
2682OSMetaClassDefineReservedUnused(IOUserClient, 3);
2683OSMetaClassDefineReservedUnused(IOUserClient, 4);
2684OSMetaClassDefineReservedUnused(IOUserClient, 5);
2685OSMetaClassDefineReservedUnused(IOUserClient, 6);
2686OSMetaClassDefineReservedUnused(IOUserClient, 7);
2687OSMetaClassDefineReservedUnused(IOUserClient, 8);
2688OSMetaClassDefineReservedUnused(IOUserClient, 9);
2689OSMetaClassDefineReservedUnused(IOUserClient, 10);
2690OSMetaClassDefineReservedUnused(IOUserClient, 11);
2691OSMetaClassDefineReservedUnused(IOUserClient, 12);
2692OSMetaClassDefineReservedUnused(IOUserClient, 13);
2693OSMetaClassDefineReservedUnused(IOUserClient, 14);
2694OSMetaClassDefineReservedUnused(IOUserClient, 15);
2695