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