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