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