]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOUserClient.cpp
xnu-1228.9.59.tar.gz
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 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>
2d21ac55 38#include <sys/proc.h>
1c79356b
A
39
40#include <IOKit/assert.h>
41
55e303ae 42#include "IOServicePrivate.h"
2d21ac55
A
43#include "IOKitKernelInternal.h"
44
45#define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
46#define SCALAR32(x) ((uint32_t )x)
47#define ARG32(x) ((void *)SCALAR32(x))
48#define REF64(x) ((io_user_reference_t)((natural_t)(x)))
49#define REF32(x) ((int)(x))
50
51enum
52{
53 kIOUCAsync0Flags = 3ULL,
54 kIOUCAsync64Flag = 1ULL
55};
55e303ae 56
1c79356b
A
57/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
58
59// definitions we should get from osfmk
60
61//typedef struct ipc_port * ipc_port_t;
62typedef natural_t ipc_kobject_type_t;
63
64#define IKOT_IOKIT_SPARE 27
65#define IKOT_IOKIT_CONNECT 29
66#define IKOT_IOKIT_OBJECT 30
67
68extern "C" {
69
70extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
71 ipc_kobject_type_t type );
72
73extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
74
75extern mach_port_name_t iokit_make_send_right( task_t task,
76 io_object_t obj, ipc_kobject_type_t type );
77
91447636
A
78extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta );
79
1c79356b
A
80extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
81
82extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
83
84extern ipc_port_t master_device_port;
85
9bccf70c
A
86extern void iokit_retain_port( ipc_port_t port );
87extern void iokit_release_port( ipc_port_t port );
88
43866e37
A
89extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type );
90
91447636 91#include <mach/mach_traps.h>
1c79356b
A
92#include <vm/vm_map.h>
93
94} /* extern "C" */
95
96
97/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
98
99// IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
100
101class IOMachPort : public OSObject
102{
103 OSDeclareDefaultStructors(IOMachPort)
104public:
105 OSObject * object;
106 ipc_port_t port;
9bccf70c 107 UInt32 mscount;
55e303ae 108 UInt8 holdDestroy;
1c79356b
A
109
110 static IOMachPort * portForObject( OSObject * obj,
111 ipc_kobject_type_t type );
9bccf70c
A
112 static bool noMoreSendersForObject( OSObject * obj,
113 ipc_kobject_type_t type, mach_port_mscount_t * mscount );
1c79356b
A
114 static void releasePortForObject( OSObject * obj,
115 ipc_kobject_type_t type );
55e303ae
A
116 static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type );
117
1c79356b
A
118 static OSDictionary * dictForType( ipc_kobject_type_t type );
119
120 static mach_port_name_t makeSendRightForTask( task_t task,
121 io_object_t obj, ipc_kobject_type_t type );
122
123 virtual void free();
124};
125
126#define super OSObject
127OSDefineMetaClassAndStructors(IOMachPort, OSObject)
128
129static IOLock * gIOObjectPortLock;
130
131/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
132
133// not in dictForType() for debugging ease
134static OSDictionary * gIOObjectPorts;
135static OSDictionary * gIOConnectPorts;
136
137OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
138{
139 OSDictionary ** dict;
140
141 if( IKOT_IOKIT_OBJECT == type )
142 dict = &gIOObjectPorts;
143 else if( IKOT_IOKIT_CONNECT == type )
144 dict = &gIOConnectPorts;
145 else
146 return( 0 );
147
148 if( 0 == *dict)
149 *dict = OSDictionary::withCapacity( 1 );
150
151 return( *dict );
152}
153
154IOMachPort * IOMachPort::portForObject ( OSObject * obj,
155 ipc_kobject_type_t type )
156{
157 IOMachPort * inst = 0;
158 OSDictionary * dict;
159
160 IOTakeLock( gIOObjectPortLock);
161
162 do {
163
164 dict = dictForType( type );
165 if( !dict)
166 continue;
167
168 if( (inst = (IOMachPort *)
9bccf70c
A
169 dict->getObject( (const OSSymbol *) obj ))) {
170 inst->mscount++;
171 inst->retain();
1c79356b 172 continue;
9bccf70c 173 }
1c79356b
A
174
175 inst = new IOMachPort;
176 if( inst && !inst->init()) {
177 inst = 0;
178 continue;
179 }
180
181 inst->port = iokit_alloc_object_port( obj, type );
182 if( inst->port) {
183 // retains obj
184 dict->setObject( (const OSSymbol *) obj, inst );
9bccf70c 185 inst->mscount++;
1c79356b
A
186
187 } else {
188 inst->release();
189 inst = 0;
190 }
191
192 } while( false );
193
194 IOUnlock( gIOObjectPortLock);
195
196 return( inst );
197}
198
9bccf70c
A
199bool IOMachPort::noMoreSendersForObject( OSObject * obj,
200 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
201{
202 OSDictionary * dict;
203 IOMachPort * machPort;
204 bool destroyed = true;
205
206 IOTakeLock( gIOObjectPortLock);
207
208 if( (dict = dictForType( type ))) {
209 obj->retain();
210
211 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
212 if( machPort) {
213 destroyed = (machPort->mscount == *mscount);
214 if( destroyed)
215 dict->removeObject( (const OSSymbol *) obj );
216 else
217 *mscount = machPort->mscount;
55e303ae 218 }
9bccf70c
A
219 obj->release();
220 }
221
222 IOUnlock( gIOObjectPortLock);
223
224 return( destroyed );
225}
226
1c79356b
A
227void IOMachPort::releasePortForObject( OSObject * obj,
228 ipc_kobject_type_t type )
229{
230 OSDictionary * dict;
55e303ae 231 IOMachPort * machPort;
1c79356b
A
232
233 IOTakeLock( gIOObjectPortLock);
234
235 if( (dict = dictForType( type ))) {
236 obj->retain();
55e303ae
A
237 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
238 if( machPort && !machPort->holdDestroy)
239 dict->removeObject( (const OSSymbol *) obj );
1c79356b
A
240 obj->release();
241 }
242
243 IOUnlock( gIOObjectPortLock);
244}
245
55e303ae
A
246void IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type )
247{
248 OSDictionary * dict;
249 IOMachPort * machPort;
250
251 IOLockLock( gIOObjectPortLock );
252
253 if( (dict = dictForType( type ))) {
254 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
255 if( machPort)
256 machPort->holdDestroy = true;
257 }
258
259 IOLockUnlock( gIOObjectPortLock );
260}
261
1c79356b
A
262void IOUserClient::destroyUserReferences( OSObject * obj )
263{
264 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
43866e37
A
265
266 // panther, 3160200
267 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
268
269 OSDictionary * dict;
270
271 IOTakeLock( gIOObjectPortLock);
272 obj->retain();
273
274 if( (dict = IOMachPort::dictForType( IKOT_IOKIT_CONNECT )))
275 {
276 IOMachPort * port;
277 port = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
278 if (port)
279 {
280 IOUserClient * uc;
281 if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings)
282 {
283 dict->setObject((const OSSymbol *) uc->mappings, port);
284 iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
285
286 uc->mappings->release();
287 uc->mappings = 0;
288 }
289 dict->removeObject( (const OSSymbol *) obj );
290 }
291 }
292 obj->release();
293 IOUnlock( gIOObjectPortLock);
1c79356b
A
294}
295
296mach_port_name_t IOMachPort::makeSendRightForTask( task_t task,
297 io_object_t obj, ipc_kobject_type_t type )
298{
299 return( iokit_make_send_right( task, obj, type ));
300}
301
302void IOMachPort::free( void )
303{
304 if( port)
305 iokit_destroy_object_port( port );
306 super::free();
307}
308
309/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
310
55e303ae
A
311class IOUserNotification : public OSIterator
312{
313 OSDeclareDefaultStructors(IOUserNotification)
314
315 IONotifier * holdNotify;
316 IOLock * lock;
317
318public:
319
320 virtual bool init( void );
321 virtual void free();
322
323 virtual void setNotification( IONotifier * obj );
324
325 virtual void reset();
326 virtual bool isValid();
327};
328
329/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
330
1c79356b
A
331extern "C" {
332
333// functions called from osfmk/device/iokit_rpc.c
334
335void
336iokit_add_reference( io_object_t obj )
337{
338 if( obj)
339 obj->retain();
340}
341
342void
343iokit_remove_reference( io_object_t obj )
344{
345 if( obj)
346 obj->release();
347}
348
349ipc_port_t
350iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
351{
352 IOMachPort * machPort;
9bccf70c 353 ipc_port_t port;
1c79356b 354
9bccf70c
A
355 if( (machPort = IOMachPort::portForObject( obj, type ))) {
356
357 port = machPort->port;
358 if( port)
359 iokit_retain_port( port );
360
361 machPort->release();
362
363 } else
364 port = NULL;
365
366 return( port );
1c79356b
A
367}
368
369kern_return_t
370iokit_client_died( io_object_t obj, ipc_port_t /* port */,
9bccf70c 371 ipc_kobject_type_t type, mach_port_mscount_t * mscount )
1c79356b
A
372{
373 IOUserClient * client;
374 IOMemoryMap * map;
55e303ae 375 IOUserNotification * notify;
1c79356b 376
9bccf70c
A
377 if( !IOMachPort::noMoreSendersForObject( obj, type, mscount ))
378 return( kIOReturnNotReady );
379
55e303ae
A
380 if( IKOT_IOKIT_CONNECT == type)
381 {
382 if( (client = OSDynamicCast( IOUserClient, obj )))
383 client->clientDied();
384 }
385 else if( IKOT_IOKIT_OBJECT == type)
386 {
387 if( (map = OSDynamicCast( IOMemoryMap, obj )))
388 map->taskDied();
389 else if( (notify = OSDynamicCast( IOUserNotification, obj )))
390 notify->setNotification( 0 );
391 }
1c79356b 392
9bccf70c 393 return( kIOReturnSuccess );
1c79356b
A
394}
395
396}; /* extern "C" */
397
398/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
399
55e303ae 400class IOServiceUserNotification : public IOUserNotification
1c79356b 401{
55e303ae 402 OSDeclareDefaultStructors(IOServiceUserNotification)
1c79356b
A
403
404 struct PingMsg {
55e303ae 405 mach_msg_header_t msgHdr;
2d21ac55 406 OSNotificationHeader64 notifyHeader;
1c79356b
A
407 };
408
ccc36f2f 409 enum { kMaxOutstanding = 1024 };
1c79356b 410
2d21ac55 411 PingMsg * pingMsg;
55e303ae 412 vm_size_t msgSize;
1c79356b
A
413 OSArray * newSet;
414 OSObject * lastEntry;
415 bool armed;
416
417public:
418
419 virtual bool init( mach_port_t port, natural_t type,
2d21ac55
A
420 void * reference, vm_size_t referenceSize,
421 bool clientIs64 );
1c79356b
A
422 virtual void free();
423
424 static bool _handler( void * target,
425 void * ref, IOService * newService );
426 virtual bool handler( void * ref, IOService * newService );
427
428 virtual OSObject * getNextObject();
429};
430
431class IOServiceMessageUserNotification : public IOUserNotification
432{
433 OSDeclareDefaultStructors(IOServiceMessageUserNotification)
434
55e303ae
A
435 struct PingMsg {
436 mach_msg_header_t msgHdr;
437 mach_msg_body_t msgBody;
438 mach_msg_port_descriptor_t ports[1];
2d21ac55 439 OSNotificationHeader64 notifyHeader;
55e303ae
A
440 };
441
442 PingMsg * pingMsg;
443 vm_size_t msgSize;
2d21ac55
A
444 uint8_t clientIs64;
445 int owningPID;
55e303ae 446
1c79356b
A
447public:
448
449 virtual bool init( mach_port_t port, natural_t type,
2d21ac55
A
450 void * reference, vm_size_t referenceSize,
451 vm_size_t extraSize,
452 bool clientIs64 );
453
1c79356b
A
454 virtual void free();
455
456 static IOReturn _handler( void * target, void * ref,
457 UInt32 messageType, IOService * provider,
458 void * messageArgument, vm_size_t argSize );
459 virtual IOReturn handler( void * ref,
460 UInt32 messageType, IOService * provider,
461 void * messageArgument, vm_size_t argSize );
462
463 virtual OSObject * getNextObject();
464};
465
466/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
467
468#undef super
469#define super OSIterator
470OSDefineMetaClass( IOUserNotification, OSIterator )
471OSDefineAbstractStructors( IOUserNotification, OSIterator )
472
473/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
474
55e303ae 475bool IOUserNotification::init( void )
1c79356b
A
476{
477 if( !super::init())
478 return( false );
479
480 lock = IOLockAlloc();
481 if( !lock)
482 return( false );
483
1c79356b
A
484 return( true );
485}
486
487void IOUserNotification::free( void )
488{
489 if( holdNotify)
490 holdNotify->remove();
491 // can't be in handler now
492
1c79356b
A
493 if( lock)
494 IOLockFree( lock );
495
496 super::free();
497}
498
499
500void IOUserNotification::setNotification( IONotifier * notify )
501{
55e303ae 502 IONotifier * previousNotify;
1c79356b 503
55e303ae
A
504 IOLockLock( gIOObjectPortLock);
505
506 previousNotify = holdNotify;
1c79356b 507 holdNotify = notify;
55e303ae
A
508
509 IOLockUnlock( gIOObjectPortLock);
510
511 if( previousNotify)
512 previousNotify->remove();
1c79356b
A
513}
514
515void IOUserNotification::reset()
516{
517 // ?
518}
519
520bool IOUserNotification::isValid()
521{
522 return( true );
523}
524
525/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
526
527#undef super
528#define super IOUserNotification
529OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
530
531/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
532
533bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
2d21ac55
A
534 void * reference, vm_size_t referenceSize,
535 bool clientIs64 )
1c79356b
A
536{
537 newSet = OSArray::withCapacity( 1 );
538 if( !newSet)
539 return( false );
540
2d21ac55
A
541 if (referenceSize > sizeof(OSAsyncReference64))
542 return( false );
543
544 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
55e303ae
A
545 pingMsg = (PingMsg *) IOMalloc( msgSize);
546 if( !pingMsg)
547 return( false );
548
549 bzero( pingMsg, msgSize);
550
551 pingMsg->msgHdr.msgh_remote_port = port;
552 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS(
553 MACH_MSG_TYPE_COPY_SEND /*remote*/,
554 MACH_MSG_TYPE_MAKE_SEND /*local*/);
555 pingMsg->msgHdr.msgh_size = msgSize;
556 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
557
558 pingMsg->notifyHeader.size = 0;
559 pingMsg->notifyHeader.type = type;
2d21ac55 560 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
55e303ae
A
561
562 return( super::init() );
1c79356b
A
563}
564
565void IOServiceUserNotification::free( void )
566{
55e303ae
A
567 PingMsg * _pingMsg;
568 vm_size_t _msgSize;
569 OSArray * _newSet;
570 OSObject * _lastEntry;
1c79356b 571
55e303ae
A
572 _pingMsg = pingMsg;
573 _msgSize = msgSize;
574 _lastEntry = lastEntry;
575 _newSet = newSet;
1c79356b
A
576
577 super::free();
55e303ae
A
578
579 if( _pingMsg && _msgSize)
580 IOFree( _pingMsg, _msgSize);
581
582 if( _lastEntry)
583 _lastEntry->release();
584
585 if( _newSet)
586 _newSet->release();
1c79356b
A
587}
588
589bool IOServiceUserNotification::_handler( void * target,
590 void * ref, IOService * newService )
591{
592 return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
593}
594
55e303ae 595bool IOServiceUserNotification::handler( void * ref,
1c79356b
A
596 IOService * newService )
597{
598 unsigned int count;
599 kern_return_t kr;
9bccf70c 600 ipc_port_t port = NULL;
1c79356b
A
601 bool sendPing = false;
602
603 IOTakeLock( lock );
604
605 count = newSet->getCount();
606 if( count < kMaxOutstanding) {
607
608 newSet->setObject( newService );
609 if( (sendPing = (armed && (0 == count))))
610 armed = false;
611 }
612
613 IOUnlock( lock );
614
55e303ae
A
615 if( kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type)
616 IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT );
617
1c79356b 618 if( sendPing) {
9bccf70c
A
619 if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) ))
620 pingMsg->msgHdr.msgh_local_port = port;
621 else
622 pingMsg->msgHdr.msgh_local_port = NULL;
1c79356b
A
623
624 kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
625 pingMsg->msgHdr.msgh_size);
9bccf70c
A
626 if( port)
627 iokit_release_port( port );
628
1c79356b
A
629 if( KERN_SUCCESS != kr)
630 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
631 }
632
633 return( true );
634}
635
636OSObject * IOServiceUserNotification::getNextObject()
637{
638 unsigned int count;
639 OSObject * result;
640
641 IOTakeLock( lock );
642
643 if( lastEntry)
644 lastEntry->release();
645
646 count = newSet->getCount();
647 if( count ) {
648 result = newSet->getObject( count - 1 );
649 result->retain();
650 newSet->removeObject( count - 1);
651 } else {
652 result = 0;
653 armed = true;
654 }
655 lastEntry = result;
656
657 IOUnlock( lock );
658
659 return( result );
660}
661
662/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
663
664OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
665
666/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
667
668bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
2d21ac55
A
669 void * reference, vm_size_t referenceSize, vm_size_t extraSize,
670 bool client64 )
1c79356b 671{
55e303ae 672
2d21ac55
A
673 if (referenceSize > sizeof(OSAsyncReference64))
674 return( false );
675
676 clientIs64 = client64;
677
678 owningPID = proc_selfpid();
679
680 extraSize += sizeof(IOServiceInterestContent64);
681 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize + extraSize;
55e303ae
A
682 pingMsg = (PingMsg *) IOMalloc( msgSize);
683 if( !pingMsg)
684 return( false );
685
686 bzero( pingMsg, msgSize);
687
688 pingMsg->msgHdr.msgh_remote_port = port;
689 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS_COMPLEX
690 | MACH_MSGH_BITS(
691 MACH_MSG_TYPE_COPY_SEND /*remote*/,
692 MACH_MSG_TYPE_MAKE_SEND /*local*/);
693 pingMsg->msgHdr.msgh_size = msgSize;
694 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID;
695
696 pingMsg->msgBody.msgh_descriptor_count = 1;
697
698 pingMsg->ports[0].name = 0;
699 pingMsg->ports[0].disposition = MACH_MSG_TYPE_MAKE_SEND;
700 pingMsg->ports[0].type = MACH_MSG_PORT_DESCRIPTOR;
701
702 pingMsg->notifyHeader.size = extraSize;
703 pingMsg->notifyHeader.type = type;
2d21ac55 704 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
55e303ae
A
705
706 return( super::init() );
1c79356b
A
707}
708
709void IOServiceMessageUserNotification::free( void )
710{
55e303ae
A
711 PingMsg * _pingMsg;
712 vm_size_t _msgSize;
713
714 _pingMsg = pingMsg;
715 _msgSize = msgSize;
716
1c79356b 717 super::free();
55e303ae
A
718
719 if( _pingMsg && _msgSize)
720 IOFree( _pingMsg, _msgSize);
1c79356b
A
721}
722
723IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
724 UInt32 messageType, IOService * provider,
725 void * argument, vm_size_t argSize )
726{
727 return( ((IOServiceMessageUserNotification *) target)->handler(
728 ref, messageType, provider, argument, argSize));
729}
730
731IOReturn IOServiceMessageUserNotification::handler( void * ref,
732 UInt32 messageType, IOService * provider,
733 void * messageArgument, vm_size_t argSize )
734{
2d21ac55
A
735 kern_return_t kr;
736 ipc_port_t thisPort, providerPort;
737 IOServiceInterestContent64 * data = (IOServiceInterestContent64 *)
738 ((((uint8_t *) pingMsg) + msgSize) - pingMsg->notifyHeader.size);
739 // == pingMsg->notifyHeader.content;
740
741 if (kIOMessageCopyClientID == messageType)
742 {
743 *((void **) messageArgument) = IOCopyLogNameForPID(owningPID);
744 return (kIOReturnSuccess);
745 }
1c79356b
A
746
747 data->messageType = messageType;
2d21ac55
A
748
749 if( argSize == 0)
750 {
751 data->messageArgument[0] = (io_user_reference_t) messageArgument;
752 if (clientIs64)
753 argSize = sizeof(data->messageArgument[0]);
754 else
755 {
756 data->messageArgument[0] |= (data->messageArgument[0] << 32);
757 argSize = sizeof(messageArgument);
758 }
759 }
760 else
761 {
1c79356b
A
762 if( argSize > kIOUserNotifyMaxMessageSize)
763 argSize = kIOUserNotifyMaxMessageSize;
764 bcopy( messageArgument, data->messageArgument, argSize );
765 }
2d21ac55
A
766 pingMsg->msgHdr.msgh_size = msgSize - pingMsg->notifyHeader.size
767 + sizeof( IOServiceInterestContent64 )
1c79356b
A
768 - sizeof( data->messageArgument)
769 + argSize;
770
55e303ae
A
771 providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
772 pingMsg->ports[0].name = providerPort;
773 thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
774 pingMsg->msgHdr.msgh_local_port = thisPort;
1c79356b 775 kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
55e303ae
A
776 pingMsg->msgHdr.msgh_size);
777 if( thisPort)
778 iokit_release_port( thisPort );
779 if( providerPort)
780 iokit_release_port( providerPort );
9bccf70c 781
1c79356b
A
782 if( KERN_SUCCESS != kr)
783 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
784
785 return( kIOReturnSuccess );
786}
787
788OSObject * IOServiceMessageUserNotification::getNextObject()
789{
790 return( 0 );
791}
792
793/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
794
795#undef super
796#define super IOService
797OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
798
799void IOUserClient::initialize( void )
800{
801 gIOObjectPortLock = IOLockAlloc();
802
803 assert( gIOObjectPortLock );
804}
805
806void IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
807 mach_port_t wakePort,
808 void *callback, void *refcon)
809{
2d21ac55
A
810 asyncRef[kIOAsyncReservedIndex] = ((natural_t) wakePort)
811 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
812 asyncRef[kIOAsyncCalloutFuncIndex] = (natural_t) callback;
1c79356b
A
813 asyncRef[kIOAsyncCalloutRefconIndex] = (natural_t) refcon;
814}
815
2d21ac55
A
816void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
817 mach_port_t wakePort,
818 mach_vm_address_t callback, io_user_reference_t refcon)
819{
820 asyncRef[kIOAsyncReservedIndex] = ((io_user_reference_t) wakePort)
821 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
822 asyncRef[kIOAsyncCalloutFuncIndex] = (io_user_reference_t) callback;
823 asyncRef[kIOAsyncCalloutRefconIndex] = refcon;
824}
825
8f6c56a5 826inline OSDictionary * CopyConsoleUser(UInt32 uid)
1c79356b 827{
8f6c56a5
A
828 OSArray * array;
829 OSDictionary * user = 0;
55e303ae
A
830
831 if ((array = OSDynamicCast(OSArray,
832 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
833 {
834 for (unsigned int idx = 0;
835 (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
8f6c56a5
A
836 idx++) {
837 OSNumber * num;
838
839 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
840 && (uid == num->unsigned32BitValue())) {
841 user->retain();
842 break;
843 }
55e303ae
A
844 }
845 array->release();
846 }
8f6c56a5 847 return user;
1c79356b
A
848}
849
8f6c56a5
A
850IOReturn IOUserClient::clientHasPrivilege( void * securityToken,
851 const char * privilegeName )
5d5c5d0d 852{
8f6c56a5
A
853 kern_return_t kr;
854 security_token_t token;
855 mach_msg_type_number_t count;
856 task_t task;
857 OSDictionary * user;
858 bool secureConsole;
5d5c5d0d 859
8f6c56a5
A
860 if ((secureConsole = !strcmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess)))
861 task = (task_t)((IOUCProcessToken *)securityToken)->token;
5d5c5d0d 862 else
8f6c56a5
A
863 task = (task_t)securityToken;
864
865 count = TASK_SECURITY_TOKEN_COUNT;
866 kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count );
867
868 if (KERN_SUCCESS != kr)
869 {}
870 else if (!strcmp(privilegeName, kIOClientPrivilegeAdministrator)) {
871 if (0 != token.val[0])
872 kr = kIOReturnNotPrivileged;
873 } else if (!strcmp(privilegeName, kIOClientPrivilegeLocalUser)) {
874 user = CopyConsoleUser(token.val[0]);
875 if ( user )
876 user->release();
877 else
878 kr = kIOReturnNotPrivileged;
879 } else if (secureConsole || !strcmp(privilegeName, kIOClientPrivilegeConsoleUser)) {
880 user = CopyConsoleUser(token.val[0]);
881 if ( user ) {
882 if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue)
883 kr = kIOReturnNotPrivileged;
884 else if ( secureConsole ) {
885 OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey));
886 if ( pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid)
887 kr = kIOReturnNotPrivileged;
888 }
889 user->release();
890 }
891 else
892 kr = kIOReturnNotPrivileged;
893 } else
894 kr = kIOReturnUnsupported;
895
896 return (kr);
5d5c5d0d
A
897}
898
0c530ab8
A
899bool IOUserClient::init()
900{
901 if( getPropertyTable())
902 return true;
903 else
904 return super::init();
905}
906
907bool IOUserClient::init(OSDictionary * dictionary)
908{
909 if( getPropertyTable())
910 return true;
911 else
912 return super::init(dictionary);
913}
914
1c79356b
A
915bool IOUserClient::initWithTask(task_t owningTask,
916 void * securityID,
917 UInt32 type )
918{
919 if( getPropertyTable())
920 return true;
921 else
922 return super::init();
923}
924
925bool IOUserClient::initWithTask(task_t owningTask,
926 void * securityID,
927 UInt32 type,
928 OSDictionary * properties )
929{
930 bool ok;
931
932 ok = super::init( properties );
933 ok &= initWithTask( owningTask, securityID, type );
934
935 return( ok );
936}
937
938void IOUserClient::free()
939{
940 if( mappings)
941 mappings->release();
942
943 super::free();
944}
945
946IOReturn IOUserClient::clientDied( void )
947{
948 return( clientClose());
949}
950
951IOReturn IOUserClient::clientClose( void )
952{
953 return( kIOReturnUnsupported );
954}
955
956IOService * IOUserClient::getService( void )
957{
958 return( 0 );
959}
960
961IOReturn IOUserClient::registerNotificationPort(
962 mach_port_t /* port */,
963 UInt32 /* type */,
964 UInt32 /* refCon */)
965{
966 return( kIOReturnUnsupported);
967}
968
969IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
970 semaphore_t * semaphore )
971{
972 return( kIOReturnUnsupported);
973}
974
975IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
976{
977 return( kIOReturnUnsupported);
978}
979
980IOReturn IOUserClient::clientMemoryForType( UInt32 type,
981 IOOptionBits * options,
982 IOMemoryDescriptor ** memory )
983{
984 return( kIOReturnUnsupported);
985}
986
987IOMemoryMap * IOUserClient::mapClientMemory(
988 IOOptionBits type,
989 task_t task,
9bccf70c
A
990 IOOptionBits mapFlags,
991 IOVirtualAddress atAddress )
1c79356b
A
992{
993 IOReturn err;
994 IOOptionBits options = 0;
995 IOMemoryDescriptor * memory;
996 IOMemoryMap * map = 0;
997
998 err = clientMemoryForType( (UInt32) type, &options, &memory );
999
1000 if( memory && (kIOReturnSuccess == err)) {
1001
1002 options = (options & ~kIOMapUserOptionsMask)
1003 | (mapFlags & kIOMapUserOptionsMask);
1004 map = memory->map( task, atAddress, options );
1005 memory->release();
1006 }
1007
1008 return( map );
1009}
1010
2d21ac55
A
1011IOMemoryMap * IOUserClient::mapClientMemory64(
1012 IOOptionBits type,
1013 task_t task,
1014 IOOptionBits mapFlags,
1015 mach_vm_address_t atAddress )
1016{
1017 IOReturn err;
1018 IOOptionBits options = 0;
1019 IOMemoryDescriptor * memory;
1020 IOMemoryMap * map = 0;
1021
1022 err = clientMemoryForType( (UInt32) type, &options, &memory );
1023
1024 if( memory && (kIOReturnSuccess == err)) {
1025
1026 options = (options & ~kIOMapUserOptionsMask)
1027 | (mapFlags & kIOMapUserOptionsMask);
1028 map = memory->createMappingInTask( task, atAddress, options );
1029 memory->release();
1030 }
1031
1032 return( map );
1033}
1034
1c79356b
A
1035IOReturn IOUserClient::exportObjectToClient(task_t task,
1036 OSObject *obj, io_object_t *clientObj)
1037{
1038 mach_port_name_t name;
1039
1040 name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
1041 assert( name );
1042
1043 *(mach_port_name_t *)clientObj = name;
1044 return kIOReturnSuccess;
1045}
1046
1047IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
1048{
1049 return( 0 );
1050}
1051
1052IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
1053{
1054 return( 0 );
1055}
1056
1057IOExternalMethod * IOUserClient::
1058getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
1059{
1060 IOExternalMethod *method = getExternalMethodForIndex(index);
1061
1062 if (method)
1063 *targetP = (IOService *) method->object;
1064
1065 return method;
1066}
1067
1068IOExternalAsyncMethod * IOUserClient::
1069getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
1070{
1071 IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
1072
1073 if (method)
1074 *targetP = (IOService *) method->object;
1075
1076 return method;
1077}
1078
1079IOExternalTrap * IOUserClient::
1080getExternalTrapForIndex(UInt32 index)
1081{
1082 return NULL;
1083}
1084
1085IOExternalTrap * IOUserClient::
1086getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
1087{
1088 IOExternalTrap *trap = getExternalTrapForIndex(index);
1089
1090 if (trap) {
1091 *targetP = trap->object;
1092 }
1093
1094 return trap;
1095}
1096
1097IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
1098 IOReturn result, void *args[], UInt32 numArgs)
1099{
2d21ac55
A
1100 OSAsyncReference64 reference64;
1101 io_user_reference_t args64[kMaxAsyncArgs];
1102 unsigned int idx;
1103
1104 if (numArgs > kMaxAsyncArgs)
1105 return kIOReturnMessageTooLarge;
1106
1107 for (idx = 0; idx < kOSAsyncRef64Count; idx++)
1108 reference64[idx] = REF64(reference[idx]);
1109
1110 for (idx = 0; idx < numArgs; idx++)
1111 args64[idx] = REF64(args[idx]);
1112
1113 return (sendAsyncResult64(reference64, result, args64, numArgs));
1114}
1115
1116IOReturn IOUserClient::sendAsyncResult64(OSAsyncReference64 reference,
1117 IOReturn result, io_user_reference_t args[], UInt32 numArgs)
1118{
1119 struct ReplyMsg
1120 {
1121 mach_msg_header_t msgHdr;
1122 union
1123 {
1124 struct
1125 {
1126 OSNotificationHeader notifyHdr;
1127 IOAsyncCompletionContent asyncContent;
1128 uint32_t args[kMaxAsyncArgs];
1129 } msg32;
1130 struct
1131 {
1132 OSNotificationHeader64 notifyHdr;
1133 IOAsyncCompletionContent asyncContent;
1134 uint32_t pad;
1135 io_user_reference_t args[kMaxAsyncArgs];
1136 } msg64;
1137 } m;
1c79356b 1138 };
2d21ac55
A
1139 ReplyMsg replyMsg;
1140 mach_port_t replyPort;
1c79356b
A
1141 kern_return_t kr;
1142
1143 // If no reply port, do nothing.
2d21ac55
A
1144 replyPort = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
1145 if (replyPort == MACH_PORT_NULL)
1c79356b
A
1146 return kIOReturnSuccess;
1147
2d21ac55 1148 if (numArgs > kMaxAsyncArgs)
1c79356b 1149 return kIOReturnMessageTooLarge;
2d21ac55 1150
55e303ae 1151 replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
2d21ac55 1152 0 /*local*/);
1c79356b 1153 replyMsg.msgHdr.msgh_remote_port = replyPort;
2d21ac55
A
1154 replyMsg.msgHdr.msgh_local_port = 0;
1155 replyMsg.msgHdr.msgh_id = kOSNotificationMessageID;
1156 if (kIOUCAsync64Flag & reference[0])
1157 {
1158 replyMsg.msgHdr.msgh_size =
1159 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg64)
1160 - (kMaxAsyncArgs - numArgs) * sizeof(io_user_reference_t);
1161 replyMsg.m.msg64.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1162 + sizeof(uint32_t)
1163 + numArgs * sizeof(io_user_reference_t);
1164 replyMsg.m.msg64.notifyHdr.type = kIOAsyncCompletionNotificationType;
1165 bcopy(reference, replyMsg.m.msg64.notifyHdr.reference, sizeof(OSAsyncReference64));
1166
1167 replyMsg.m.msg64.asyncContent.result = result;
1168 if (numArgs)
1169 bcopy(args, replyMsg.m.msg64.args, numArgs * sizeof(io_user_reference_t));
1170 }
1171 else
1172 {
1173 unsigned int idx;
1174
1175 replyMsg.msgHdr.msgh_size =
1176 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg32)
1177 - (kMaxAsyncArgs - numArgs) * sizeof(uint32_t);
1178
1179 replyMsg.m.msg32.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1180 + numArgs * sizeof(uint32_t);
1181 replyMsg.m.msg32.notifyHdr.type = kIOAsyncCompletionNotificationType;
1c79356b 1182
2d21ac55
A
1183 for (idx = 0; idx < kOSAsyncRefCount; idx++)
1184 replyMsg.m.msg32.notifyHdr.reference[idx] = REF32(reference[idx]);
1185
1186 replyMsg.m.msg32.asyncContent.result = result;
1187
1188 for (idx = 0; idx < numArgs; idx++)
1189 replyMsg.m.msg32.args[idx] = REF32(args[idx]);
1190 }
1c79356b 1191
1c79356b
A
1192 kr = mach_msg_send_from_kernel( &replyMsg.msgHdr,
1193 replyMsg.msgHdr.msgh_size);
1194 if( KERN_SUCCESS != kr)
1195 IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
1196 return kr;
1197}
1198
2d21ac55 1199
1c79356b
A
1200/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1201
1c79356b
A
1202extern "C" {
1203
1204#define CHECK(cls,obj,out) \
1205 cls * out; \
1206 if( !(out = OSDynamicCast( cls, obj))) \
1207 return( kIOReturnBadArgument )
1208
1209/* Routine io_object_get_class */
1210kern_return_t is_io_object_get_class(
1211 io_object_t object,
1212 io_name_t className )
1213{
91447636
A
1214 const OSMetaClass* my_obj = NULL;
1215
1c79356b
A
1216 if( !object)
1217 return( kIOReturnBadArgument );
91447636
A
1218
1219 my_obj = object->getMetaClass();
1220 if (!my_obj) {
1221 return (kIOReturnNotFound);
1222 }
1223
1224 strcpy( className, my_obj->getClassName());
1c79356b
A
1225 return( kIOReturnSuccess );
1226}
1227
91447636
A
1228/* Routine io_object_get_superclass */
1229kern_return_t is_io_object_get_superclass(
1230 mach_port_t master_port,
1231 io_name_t obj_name,
1232 io_name_t class_name)
1233{
1234 const OSMetaClass* my_obj = NULL;
1235 const OSMetaClass* superclass = NULL;
1236 const OSSymbol *my_name = NULL;
1237 const char *my_cstr = NULL;
1238
1239 if (!obj_name || !class_name)
1240 return (kIOReturnBadArgument);
1241
1242 if( master_port != master_device_port)
1243 return( kIOReturnNotPrivileged);
1244
1245 my_name = OSSymbol::withCString(obj_name);
1246
1247 if (my_name) {
1248 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1249 my_name->release();
1250 }
1251 if (my_obj) {
1252 superclass = my_obj->getSuperClass();
1253 }
1254
1255 if (!superclass) {
1256 return( kIOReturnNotFound );
1257 }
1258
1259 my_cstr = superclass->getClassName();
1260
1261 if (my_cstr) {
2d21ac55 1262 strlcpy(class_name, my_cstr, sizeof(io_name_t));
91447636
A
1263 return( kIOReturnSuccess );
1264 }
1265 return (kIOReturnNotFound);
1266}
1267
1268/* Routine io_object_get_bundle_identifier */
1269kern_return_t is_io_object_get_bundle_identifier(
1270 mach_port_t master_port,
1271 io_name_t obj_name,
1272 io_name_t bundle_name)
1273{
1274 const OSMetaClass* my_obj = NULL;
1275 const OSSymbol *my_name = NULL;
1276 const OSSymbol *identifier = NULL;
1277 const char *my_cstr = NULL;
1278
1279 if (!obj_name || !bundle_name)
1280 return (kIOReturnBadArgument);
1281
1282 if( master_port != master_device_port)
1283 return( kIOReturnNotPrivileged);
1284
1285 my_name = OSSymbol::withCString(obj_name);
1286
1287 if (my_name) {
1288 my_obj = OSMetaClass::getMetaClassWithName(my_name);
1289 my_name->release();
1290 }
1291
1292 if (my_obj) {
1293 identifier = my_obj->getKmodName();
1294 }
1295 if (!identifier) {
1296 return( kIOReturnNotFound );
1297 }
1298
1299 my_cstr = identifier->getCStringNoCopy();
1300 if (my_cstr) {
2d21ac55 1301 strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
91447636
A
1302 return( kIOReturnSuccess );
1303 }
1304
1305 return (kIOReturnBadArgument);
1306}
1307
1c79356b
A
1308/* Routine io_object_conforms_to */
1309kern_return_t is_io_object_conforms_to(
1310 io_object_t object,
1311 io_name_t className,
1312 boolean_t *conforms )
1313{
1314 if( !object)
1315 return( kIOReturnBadArgument );
1316
1317 *conforms = (0 != object->metaCast( className ));
1318 return( kIOReturnSuccess );
1319}
1320
1321/* Routine io_object_get_retain_count */
1322kern_return_t is_io_object_get_retain_count(
1323 io_object_t object,
2d21ac55 1324 uint32_t *retainCount )
1c79356b
A
1325{
1326 if( !object)
1327 return( kIOReturnBadArgument );
1328
1329 *retainCount = object->getRetainCount();
1330 return( kIOReturnSuccess );
1331}
1332
1333/* Routine io_iterator_next */
1334kern_return_t is_io_iterator_next(
1335 io_object_t iterator,
1336 io_object_t *object )
1337{
1338 OSObject * obj;
1339
1340 CHECK( OSIterator, iterator, iter );
1341
1342 obj = iter->getNextObject();
1343 if( obj) {
1344 obj->retain();
1345 *object = obj;
1346 return( kIOReturnSuccess );
1347 } else
1348 return( kIOReturnNoDevice );
1349}
1350
1351/* Routine io_iterator_reset */
1352kern_return_t is_io_iterator_reset(
1353 io_object_t iterator )
1354{
1355 CHECK( OSIterator, iterator, iter );
1356
1357 iter->reset();
1358
1359 return( kIOReturnSuccess );
1360}
1361
1362/* Routine io_iterator_is_valid */
1363kern_return_t is_io_iterator_is_valid(
1364 io_object_t iterator,
1365 boolean_t *is_valid )
1366{
1367 CHECK( OSIterator, iterator, iter );
1368
1369 *is_valid = iter->isValid();
1370
1371 return( kIOReturnSuccess );
1372}
1373
1374/* Routine io_service_match_property_table */
1375kern_return_t is_io_service_match_property_table(
1376 io_service_t _service,
1377 io_string_t matching,
1378 boolean_t *matches )
1379{
1380 CHECK( IOService, _service, service );
1381
1382 kern_return_t kr;
1383 OSObject * obj;
1384 OSDictionary * dict;
1385
1386 obj = OSUnserializeXML( matching );
1387
1388 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1389 *matches = service->passiveMatch( dict );
1390 kr = kIOReturnSuccess;
1391 } else
1392 kr = kIOReturnBadArgument;
1393
1394 if( obj)
1395 obj->release();
1396
1397 return( kr );
1398}
1399
55e303ae
A
1400/* Routine io_service_match_property_table_ool */
1401kern_return_t is_io_service_match_property_table_ool(
1402 io_object_t service,
1403 io_buf_ptr_t matching,
1404 mach_msg_type_number_t matchingCnt,
2d21ac55 1405 kern_return_t *result,
55e303ae
A
1406 boolean_t *matches )
1407{
1408 kern_return_t kr;
1409 vm_offset_t data;
91447636 1410 vm_map_offset_t map_data;
55e303ae 1411
91447636
A
1412 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1413 data = CAST_DOWN(vm_offset_t, map_data);
55e303ae
A
1414
1415 if( KERN_SUCCESS == kr) {
1416 // must return success after vm_map_copyout() succeeds
1417 *result = is_io_service_match_property_table( service,
1418 (char *) data, matches );
1419 vm_deallocate( kernel_map, data, matchingCnt );
1420 }
1421
1422 return( kr );
1423}
1424
1c79356b
A
1425/* Routine io_service_get_matching_services */
1426kern_return_t is_io_service_get_matching_services(
1427 mach_port_t master_port,
1428 io_string_t matching,
1429 io_iterator_t *existing )
1430{
1431 kern_return_t kr;
1432 OSObject * obj;
1433 OSDictionary * dict;
1434
1435 if( master_port != master_device_port)
1436 return( kIOReturnNotPrivileged);
1437
1438 obj = OSUnserializeXML( matching );
1439
1440 if( (dict = OSDynamicCast( OSDictionary, obj))) {
1c79356b
A
1441 *existing = IOService::getMatchingServices( dict );
1442 kr = kIOReturnSuccess;
1443 } else
1444 kr = kIOReturnBadArgument;
1445
1446 if( obj)
1447 obj->release();
1448
1449 return( kr );
1450}
1451
55e303ae
A
1452/* Routine io_service_get_matching_services_ool */
1453kern_return_t is_io_service_get_matching_services_ool(
1454 mach_port_t master_port,
1455 io_buf_ptr_t matching,
1456 mach_msg_type_number_t matchingCnt,
2d21ac55 1457 kern_return_t *result,
55e303ae
A
1458 io_object_t *existing )
1459{
1460 kern_return_t kr;
1461 vm_offset_t data;
91447636 1462 vm_map_offset_t map_data;
55e303ae 1463
91447636
A
1464 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1465 data = CAST_DOWN(vm_offset_t, map_data);
55e303ae
A
1466
1467 if( KERN_SUCCESS == kr) {
1468 // must return success after vm_map_copyout() succeeds
1469 *result = is_io_service_get_matching_services( master_port,
1470 (char *) data, existing );
1471 vm_deallocate( kernel_map, data, matchingCnt );
1472 }
1473
1474 return( kr );
1475}
1476
2d21ac55 1477static kern_return_t internal_io_service_add_notification(
1c79356b
A
1478 mach_port_t master_port,
1479 io_name_t notification_type,
1480 io_string_t matching,
1481 mach_port_t port,
2d21ac55
A
1482 void * reference,
1483 vm_size_t referenceSize,
1484 bool client64,
1c79356b
A
1485 io_object_t * notification )
1486{
1c79356b
A
1487 IOServiceUserNotification * userNotify = 0;
1488 IONotifier * notify = 0;
1489 const OSSymbol * sym;
1490 OSDictionary * dict;
1491 IOReturn err;
1492 unsigned long int userMsgType;
1493
1494
1495 if( master_port != master_device_port)
1496 return( kIOReturnNotPrivileged);
1497
1498 do {
1499 err = kIOReturnNoResources;
1500
1501 if( !(sym = OSSymbol::withCString( notification_type )))
1502 err = kIOReturnNoResources;
1503
1504 if( !(dict = OSDynamicCast( OSDictionary,
1505 OSUnserializeXML( matching )))) {
1506 err = kIOReturnBadArgument;
1507 continue;
1508 }
1c79356b
A
1509
1510 if( (sym == gIOPublishNotification)
1511 || (sym == gIOFirstPublishNotification))
1512 userMsgType = kIOServicePublishNotificationType;
1513 else if( (sym == gIOMatchedNotification)
1514 || (sym == gIOFirstMatchNotification))
1515 userMsgType = kIOServiceMatchedNotificationType;
1516 else if( sym == gIOTerminatedNotification)
1517 userMsgType = kIOServiceTerminatedNotificationType;
1518 else
1519 userMsgType = kLastIOKitNotificationType;
1520
1521 userNotify = new IOServiceUserNotification;
1522
1523 if( userNotify && !userNotify->init( port, userMsgType,
2d21ac55 1524 reference, referenceSize, client64)) {
1c79356b
A
1525 userNotify->release();
1526 userNotify = 0;
1527 }
1528 if( !userNotify)
1529 continue;
1530
1531 notify = IOService::addNotification( sym, dict,
1532 &userNotify->_handler, userNotify );
1533 if( notify) {
1534 dict = 0;
1535 *notification = userNotify;
1536 userNotify->setNotification( notify );
1537 err = kIOReturnSuccess;
1538 } else
1539 err = kIOReturnUnsupported;
1540
1541 } while( false );
1542
1543 if( sym)
1544 sym->release();
1545 if( dict)
1546 dict->release();
1547
1548 return( err );
1549}
1550
2d21ac55
A
1551
1552/* Routine io_service_add_notification */
1553kern_return_t is_io_service_add_notification(
1554 mach_port_t master_port,
1555 io_name_t notification_type,
1556 io_string_t matching,
1557 mach_port_t port,
1558 io_async_ref_t reference,
1559 mach_msg_type_number_t referenceCnt,
1560 io_object_t * notification )
1561{
1562 return (internal_io_service_add_notification(master_port, notification_type,
1563 matching, port, &reference[0], sizeof(io_async_ref_t),
1564 false, notification));
1565}
1566
1567/* Routine io_service_add_notification_64 */
1568kern_return_t is_io_service_add_notification_64(
1569 mach_port_t master_port,
1570 io_name_t notification_type,
1571 io_string_t matching,
1572 mach_port_t wake_port,
1573 io_async_ref64_t reference,
1574 mach_msg_type_number_t referenceCnt,
1575 io_object_t *notification )
1576{
1577 return (internal_io_service_add_notification(master_port, notification_type,
1578 matching, wake_port, &reference[0], sizeof(io_async_ref64_t),
1579 true, notification));
1580}
1581
1582
1583static kern_return_t internal_io_service_add_notification_ool(
55e303ae
A
1584 mach_port_t master_port,
1585 io_name_t notification_type,
1586 io_buf_ptr_t matching,
1587 mach_msg_type_number_t matchingCnt,
1588 mach_port_t wake_port,
2d21ac55
A
1589 void * reference,
1590 vm_size_t referenceSize,
1591 bool client64,
1592 kern_return_t *result,
55e303ae
A
1593 io_object_t *notification )
1594{
1595 kern_return_t kr;
1596 vm_offset_t data;
91447636 1597 vm_map_offset_t map_data;
55e303ae 1598
91447636
A
1599 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1600 data = CAST_DOWN(vm_offset_t, map_data);
55e303ae
A
1601
1602 if( KERN_SUCCESS == kr) {
1603 // must return success after vm_map_copyout() succeeds
2d21ac55
A
1604 *result = internal_io_service_add_notification( master_port, notification_type,
1605 (char *) data, wake_port, reference, referenceSize, client64, notification );
55e303ae
A
1606 vm_deallocate( kernel_map, data, matchingCnt );
1607 }
1608
1609 return( kr );
1610}
1611
2d21ac55
A
1612/* Routine io_service_add_notification_ool */
1613kern_return_t is_io_service_add_notification_ool(
1614 mach_port_t master_port,
1615 io_name_t notification_type,
1616 io_buf_ptr_t matching,
1617 mach_msg_type_number_t matchingCnt,
1618 mach_port_t wake_port,
1619 io_async_ref_t reference,
1620 mach_msg_type_number_t referenceCnt,
1621 kern_return_t *result,
1622 io_object_t *notification )
1623{
1624 return (internal_io_service_add_notification_ool(master_port, notification_type,
1625 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref_t),
1626 false, result, notification));
1627}
1628
1629/* Routine io_service_add_notification_ool_64 */
1630kern_return_t is_io_service_add_notification_ool_64(
1631 mach_port_t master_port,
1632 io_name_t notification_type,
1633 io_buf_ptr_t matching,
1634 mach_msg_type_number_t matchingCnt,
1635 mach_port_t wake_port,
1636 io_async_ref64_t reference,
1637 mach_msg_type_number_t referenceCnt,
1638 kern_return_t *result,
1639 io_object_t *notification )
1640{
1641 return (internal_io_service_add_notification_ool(master_port, notification_type,
1642 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref64_t),
1643 true, result, notification));
1644}
55e303ae 1645
1c79356b
A
1646/* Routine io_service_add_notification_old */
1647kern_return_t is_io_service_add_notification_old(
1648 mach_port_t master_port,
1649 io_name_t notification_type,
1650 io_string_t matching,
1651 mach_port_t port,
1652 natural_t ref,
1653 io_object_t * notification )
1654{
1655 return( is_io_service_add_notification( master_port, notification_type,
1656 matching, port, &ref, 1, notification ));
1657}
1658
2d21ac55
A
1659
1660static kern_return_t internal_io_service_add_interest_notification(
1c79356b
A
1661 io_object_t _service,
1662 io_name_t type_of_interest,
1663 mach_port_t port,
2d21ac55
A
1664 void * reference,
1665 vm_size_t referenceSize,
1666 bool client64,
1c79356b
A
1667 io_object_t * notification )
1668{
1669
1670 IOServiceMessageUserNotification * userNotify = 0;
1671 IONotifier * notify = 0;
1672 const OSSymbol * sym;
1673 IOReturn err;
1674
1675 CHECK( IOService, _service, service );
1676
1677 err = kIOReturnNoResources;
1678 if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1679
1680 userNotify = new IOServiceMessageUserNotification;
1681
1682 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
2d21ac55
A
1683 reference, referenceSize,
1684 kIOUserNotifyMaxMessageSize,
1685 client64 )) {
1c79356b
A
1686 userNotify->release();
1687 userNotify = 0;
1688 }
1689 if( !userNotify)
1690 continue;
1691
1692 notify = service->registerInterest( sym,
1693 &userNotify->_handler, userNotify );
1694 if( notify) {
1695 *notification = userNotify;
1696 userNotify->setNotification( notify );
1697 err = kIOReturnSuccess;
1698 } else
1699 err = kIOReturnUnsupported;
1700
55e303ae
A
1701 sym->release();
1702
1c79356b
A
1703 } while( false );
1704
1705 return( err );
1706}
1707
2d21ac55
A
1708/* Routine io_service_add_message_notification */
1709kern_return_t is_io_service_add_interest_notification(
1710 io_object_t service,
1711 io_name_t type_of_interest,
1712 mach_port_t port,
1713 io_async_ref_t reference,
1714 mach_msg_type_number_t referenceCnt,
1715 io_object_t * notification )
1716{
1717 return (internal_io_service_add_interest_notification(service, type_of_interest,
1718 port, &reference[0], sizeof(io_async_ref_t), false, notification));
1719}
1720
1721/* Routine io_service_add_interest_notification_64 */
1722kern_return_t is_io_service_add_interest_notification_64(
1723 io_object_t service,
1724 io_name_t type_of_interest,
1725 mach_port_t wake_port,
1726 io_async_ref64_t reference,
1727 mach_msg_type_number_t referenceCnt,
1728 io_object_t *notification )
1729{
1730 return (internal_io_service_add_interest_notification(service, type_of_interest,
1731 wake_port, &reference[0], sizeof(io_async_ref64_t), true, notification));
1732}
1733
1734
1c79356b
A
1735/* Routine io_service_acknowledge_notification */
1736kern_return_t is_io_service_acknowledge_notification(
1737 io_object_t _service,
1738 natural_t notify_ref,
1739 natural_t response )
1740{
1741 CHECK( IOService, _service, service );
1742
1743 return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1744 (IOOptionBits) response ));
1745
1746}
1747
1748/* Routine io_connect_get_semaphore */
1749kern_return_t is_io_connect_get_notification_semaphore(
1750 io_connect_t connection,
1751 natural_t notification_type,
1752 semaphore_t *semaphore )
1753{
1754 CHECK( IOUserClient, connection, client );
1755
1756 return( client->getNotificationSemaphore( (UInt32) notification_type,
1757 semaphore ));
1758}
1759
1760/* Routine io_registry_get_root_entry */
1761kern_return_t is_io_registry_get_root_entry(
1762 mach_port_t master_port,
1763 io_object_t *root )
1764{
1765 IORegistryEntry * entry;
1766
1767 if( master_port != master_device_port)
1768 return( kIOReturnNotPrivileged);
1769
1770 entry = IORegistryEntry::getRegistryRoot();
1771 if( entry)
1772 entry->retain();
1773 *root = entry;
1774
1775 return( kIOReturnSuccess );
1776}
1777
1778/* Routine io_registry_create_iterator */
1779kern_return_t is_io_registry_create_iterator(
1780 mach_port_t master_port,
1781 io_name_t plane,
2d21ac55 1782 uint32_t options,
1c79356b
A
1783 io_object_t *iterator )
1784{
1785 if( master_port != master_device_port)
1786 return( kIOReturnNotPrivileged);
1787
1788 *iterator = IORegistryIterator::iterateOver(
1789 IORegistryEntry::getPlane( plane ), options );
1790
1791 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1792}
1793
1794/* Routine io_registry_entry_create_iterator */
1795kern_return_t is_io_registry_entry_create_iterator(
1796 io_object_t registry_entry,
1797 io_name_t plane,
2d21ac55 1798 uint32_t options,
1c79356b
A
1799 io_object_t *iterator )
1800{
1801 CHECK( IORegistryEntry, registry_entry, entry );
1802
1803 *iterator = IORegistryIterator::iterateOver( entry,
1804 IORegistryEntry::getPlane( plane ), options );
1805
1806 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
1807}
1808
1809/* Routine io_registry_iterator_enter */
1810kern_return_t is_io_registry_iterator_enter_entry(
1811 io_object_t iterator )
1812{
1813 CHECK( IORegistryIterator, iterator, iter );
1814
1815 iter->enterEntry();
1816
1817 return( kIOReturnSuccess );
1818}
1819
1820/* Routine io_registry_iterator_exit */
1821kern_return_t is_io_registry_iterator_exit_entry(
1822 io_object_t iterator )
1823{
1824 bool didIt;
1825
1826 CHECK( IORegistryIterator, iterator, iter );
1827
1828 didIt = iter->exitEntry();
1829
1830 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
1831}
1832
1833/* Routine io_registry_entry_from_path */
1834kern_return_t is_io_registry_entry_from_path(
1835 mach_port_t master_port,
1836 io_string_t path,
1837 io_object_t *registry_entry )
1838{
1839 IORegistryEntry * entry;
1840
1841 if( master_port != master_device_port)
1842 return( kIOReturnNotPrivileged);
1843
1844 entry = IORegistryEntry::fromPath( path );
1845
1846 *registry_entry = entry;
1847
1848 return( kIOReturnSuccess );
1849}
1850
1851/* Routine io_registry_entry_in_plane */
1852kern_return_t is_io_registry_entry_in_plane(
1853 io_object_t registry_entry,
1854 io_name_t plane,
1855 boolean_t *inPlane )
1856{
1857 CHECK( IORegistryEntry, registry_entry, entry );
1858
1859 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
1860
1861 return( kIOReturnSuccess );
1862}
1863
1864
1865/* Routine io_registry_entry_get_path */
1866kern_return_t is_io_registry_entry_get_path(
1867 io_object_t registry_entry,
1868 io_name_t plane,
1869 io_string_t path )
1870{
1871 int length;
1872 CHECK( IORegistryEntry, registry_entry, entry );
1873
1874 length = sizeof( io_string_t);
1875 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
1876 return( kIOReturnSuccess );
1877 else
1878 return( kIOReturnBadArgument );
1879}
1880
1881
1882/* Routine io_registry_entry_get_name */
1883kern_return_t is_io_registry_entry_get_name(
1884 io_object_t registry_entry,
1885 io_name_t name )
1886{
1887 CHECK( IORegistryEntry, registry_entry, entry );
1888
1889 strncpy( name, entry->getName(), sizeof( io_name_t));
1890
1891 return( kIOReturnSuccess );
1892}
1893
1894/* Routine io_registry_entry_get_name_in_plane */
1895kern_return_t is_io_registry_entry_get_name_in_plane(
1896 io_object_t registry_entry,
0b4e3aa0 1897 io_name_t planeName,
1c79356b
A
1898 io_name_t name )
1899{
0b4e3aa0 1900 const IORegistryPlane * plane;
1c79356b
A
1901 CHECK( IORegistryEntry, registry_entry, entry );
1902
0b4e3aa0
A
1903 if( planeName[0])
1904 plane = IORegistryEntry::getPlane( planeName );
1905 else
1906 plane = 0;
1907
1908 strncpy( name, entry->getName( plane), sizeof( io_name_t));
1c79356b
A
1909
1910 return( kIOReturnSuccess );
1911}
1912
0b4e3aa0
A
1913/* Routine io_registry_entry_get_location_in_plane */
1914kern_return_t is_io_registry_entry_get_location_in_plane(
1915 io_object_t registry_entry,
1916 io_name_t planeName,
1917 io_name_t location )
1918{
1919 const IORegistryPlane * plane;
1920 CHECK( IORegistryEntry, registry_entry, entry );
1921
1922 if( planeName[0])
1923 plane = IORegistryEntry::getPlane( planeName );
1924 else
1925 plane = 0;
1926
1927 const char * cstr = entry->getLocation( plane );
1928
1929 if( cstr) {
1930 strncpy( location, cstr, sizeof( io_name_t));
1931 return( kIOReturnSuccess );
1932 } else
1933 return( kIOReturnNotFound );
1934}
1935
1c79356b
A
1936// Create a vm_map_copy_t or kalloc'ed data for memory
1937// to be copied out. ipc will free after the copyout.
1938
1939static kern_return_t copyoutkdata( void * data, vm_size_t len,
1940 io_buf_ptr_t * buf )
1941{
1942 kern_return_t err;
1943 vm_map_copy_t copy;
1944
91447636 1945 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
0b4e3aa0
A
1946 false /* src_destroy */, &copy);
1947
1948 assert( err == KERN_SUCCESS );
1949 if( err == KERN_SUCCESS )
1950 *buf = (char *) copy;
1951
1952 return( err );
1953}
1954
1955/* Routine io_registry_entry_get_property */
1956kern_return_t is_io_registry_entry_get_property_bytes(
1957 io_object_t registry_entry,
1958 io_name_t property_name,
2d21ac55 1959 io_struct_inband_t buf,
0b4e3aa0
A
1960 mach_msg_type_number_t *dataCnt )
1961{
1962 OSObject * obj;
1963 OSData * data;
1964 OSString * str;
1965 OSBoolean * boo;
1966 OSNumber * off;
1967 UInt64 offsetBytes;
1968 unsigned int len = 0;
1969 const void * bytes = 0;
1970 IOReturn ret = kIOReturnSuccess;
1971
1972 CHECK( IORegistryEntry, registry_entry, entry );
1973
0b4e3aa0 1974 obj = entry->copyProperty(property_name);
0b4e3aa0
A
1975 if( !obj)
1976 return( kIOReturnNoResources );
1977
1978 // One day OSData will be a common container base class
1979 // until then...
1980 if( (data = OSDynamicCast( OSData, obj ))) {
1981 len = data->getLength();
1982 bytes = data->getBytesNoCopy();
1983
1984 } else if( (str = OSDynamicCast( OSString, obj ))) {
1985 len = str->getLength() + 1;
1986 bytes = str->getCStringNoCopy();
1987
1988 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
1989 len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
1990 bytes = boo->isTrue() ? "Yes" : "No";
1991
1992 } else if( (off = OSDynamicCast( OSNumber, obj ))) {
1993 offsetBytes = off->unsigned64BitValue();
1994 len = off->numberOfBytes();
1995 bytes = &offsetBytes;
55e303ae 1996#ifdef __BIG_ENDIAN__
0b4e3aa0
A
1997 bytes = (const void *)
1998 (((UInt32) bytes) + (sizeof( UInt64) - len));
1999#endif
2000
2001 } else
2002 ret = kIOReturnBadArgument;
2003
2004 if( bytes) {
2005 if( *dataCnt < len)
2006 ret = kIOReturnIPCError;
2007 else {
2008 *dataCnt = len;
2009 bcopy( bytes, buf, len );
2010 }
2011 }
2012 obj->release();
2013
2014 return( ret );
2015}
2016
0c530ab8 2017
0b4e3aa0
A
2018/* Routine io_registry_entry_get_property */
2019kern_return_t is_io_registry_entry_get_property(
2020 io_object_t registry_entry,
2021 io_name_t property_name,
2022 io_buf_ptr_t *properties,
2023 mach_msg_type_number_t *propertiesCnt )
2024{
2025 kern_return_t err;
2026 vm_size_t len;
2027 OSObject * obj;
2028
2029 CHECK( IORegistryEntry, registry_entry, entry );
2030
0b4e3aa0 2031 obj = entry->copyProperty(property_name);
0b4e3aa0
A
2032 if( !obj)
2033 return( kIOReturnNotFound );
2034
2035 OSSerialize * s = OSSerialize::withCapacity(4096);
2036 if( !s) {
2037 obj->release();
2038 return( kIOReturnNoMemory );
2039 }
2040 s->clearText();
2041
2042 if( obj->serialize( s )) {
2043 len = s->getLength();
2044 *propertiesCnt = len;
2045 err = copyoutkdata( s->text(), len, properties );
2046
2047 } else
2048 err = kIOReturnUnsupported;
2049
2050 s->release();
2051 obj->release();
1c79356b 2052
1c79356b
A
2053 return( err );
2054}
2055
0b4e3aa0
A
2056/* Routine io_registry_entry_get_property_recursively */
2057kern_return_t is_io_registry_entry_get_property_recursively(
2058 io_object_t registry_entry,
2059 io_name_t plane,
2060 io_name_t property_name,
2d21ac55 2061 uint32_t options,
0b4e3aa0
A
2062 io_buf_ptr_t *properties,
2063 mach_msg_type_number_t *propertiesCnt )
2064{
2065 kern_return_t err;
2066 vm_size_t len;
2067 OSObject * obj;
2068
2069 CHECK( IORegistryEntry, registry_entry, entry );
2070
0b4e3aa0
A
2071 obj = entry->copyProperty( property_name,
2072 IORegistryEntry::getPlane( plane ), options);
0b4e3aa0
A
2073 if( !obj)
2074 return( kIOReturnNotFound );
2075
2076 OSSerialize * s = OSSerialize::withCapacity(4096);
2077 if( !s) {
2078 obj->release();
2079 return( kIOReturnNoMemory );
2080 }
2081
2082 s->clearText();
2083
2084 if( obj->serialize( s )) {
2085 len = s->getLength();
2086 *propertiesCnt = len;
2087 err = copyoutkdata( s->text(), len, properties );
2088
2089 } else
2090 err = kIOReturnUnsupported;
2091
2092 s->release();
2093 obj->release();
2094
2095 return( err );
2096}
1c79356b
A
2097
2098/* Routine io_registry_entry_get_properties */
2099kern_return_t is_io_registry_entry_get_properties(
2100 io_object_t registry_entry,
2101 io_buf_ptr_t *properties,
2102 mach_msg_type_number_t *propertiesCnt )
2103{
2104 kern_return_t err;
2105 vm_size_t len;
2106
2107 CHECK( IORegistryEntry, registry_entry, entry );
2108
2109 OSSerialize * s = OSSerialize::withCapacity(4096);
1c79356b
A
2110 if( !s)
2111 return( kIOReturnNoMemory );
2112
2113 s->clearText();
2114
2115 if( entry->serializeProperties( s )) {
2116 len = s->getLength();
2117 *propertiesCnt = len;
2118 err = copyoutkdata( s->text(), len, properties );
2119
2120 } else
2121 err = kIOReturnUnsupported;
2122
0b4e3aa0 2123 s->release();
1c79356b
A
2124
2125 return( err );
2126}
2127
2128/* Routine io_registry_entry_set_properties */
2129kern_return_t is_io_registry_entry_set_properties
2130(
2131 io_object_t registry_entry,
2132 io_buf_ptr_t properties,
2133 mach_msg_type_number_t propertiesCnt,
2d21ac55 2134 kern_return_t * result)
1c79356b
A
2135{
2136 OSObject * obj;
2137 kern_return_t err;
2138 IOReturn res;
2139 vm_offset_t data;
91447636 2140 vm_map_offset_t map_data;
1c79356b
A
2141
2142 CHECK( IORegistryEntry, registry_entry, entry );
2143
91447636
A
2144 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2145 data = CAST_DOWN(vm_offset_t, map_data);
1c79356b
A
2146
2147 if( KERN_SUCCESS == err) {
2148
2149 // must return success after vm_map_copyout() succeeds
2150 obj = OSUnserializeXML( (const char *) data );
2151 vm_deallocate( kernel_map, data, propertiesCnt );
2152
2153 if( obj) {
2154 res = entry->setProperties( obj );
2155 obj->release();
2156 } else
2157 res = kIOReturnBadArgument;
2158 } else
2159 res = err;
2160
2161 *result = res;
2162 return( err );
2163}
2164
1c79356b
A
2165/* Routine io_registry_entry_get_child_iterator */
2166kern_return_t is_io_registry_entry_get_child_iterator(
2167 io_object_t registry_entry,
2168 io_name_t plane,
2169 io_object_t *iterator )
2170{
2171 CHECK( IORegistryEntry, registry_entry, entry );
2172
2173 *iterator = entry->getChildIterator(
2174 IORegistryEntry::getPlane( plane ));
2175
2176 return( kIOReturnSuccess );
2177}
2178
2179/* Routine io_registry_entry_get_parent_iterator */
2180kern_return_t is_io_registry_entry_get_parent_iterator(
2181 io_object_t registry_entry,
2182 io_name_t plane,
2183 io_object_t *iterator)
2184{
2185 CHECK( IORegistryEntry, registry_entry, entry );
2186
2187 *iterator = entry->getParentIterator(
2188 IORegistryEntry::getPlane( plane ));
2189
2190 return( kIOReturnSuccess );
2191}
2192
2193/* Routine io_service_get_busy_state */
2194kern_return_t is_io_service_get_busy_state(
2195 io_object_t _service,
2d21ac55 2196 uint32_t *busyState )
1c79356b
A
2197{
2198 CHECK( IOService, _service, service );
2199
2200 *busyState = service->getBusyState();
2201
2202 return( kIOReturnSuccess );
2203}
2204
55e303ae
A
2205/* Routine io_service_get_state */
2206kern_return_t is_io_service_get_state(
2207 io_object_t _service,
2208 uint64_t *state )
2209{
2210 CHECK( IOService, _service, service );
2211
2212 *state = service->getState();
2213
2214 return( kIOReturnSuccess );
2215}
2216
1c79356b
A
2217/* Routine io_service_wait_quiet */
2218kern_return_t is_io_service_wait_quiet(
2219 io_object_t _service,
2220 mach_timespec_t wait_time )
2221{
2222 CHECK( IOService, _service, service );
2223
2224 return( service->waitQuiet( &wait_time ));
2225}
2226
2227/* Routine io_service_request_probe */
2228kern_return_t is_io_service_request_probe(
2229 io_object_t _service,
2d21ac55 2230 uint32_t options )
1c79356b
A
2231{
2232 CHECK( IOService, _service, service );
2233
2234 return( service->requestProbe( options ));
2235}
2236
2237
2238/* Routine io_service_open */
2239kern_return_t is_io_service_open(
2240 io_object_t _service,
2241 task_t owningTask,
2d21ac55 2242 uint32_t connect_type,
1c79356b
A
2243 io_object_t *connection )
2244{
2245 IOUserClient * client;
2246 IOReturn err;
2247
2248 CHECK( IOService, _service, service );
2249
2250 err = service->newUserClient( owningTask, (void *) owningTask,
0c530ab8 2251 connect_type, 0, &client );
1c79356b
A
2252
2253 if( err == kIOReturnSuccess) {
2254 assert( OSDynamicCast(IOUserClient, client) );
2255 *connection = client;
2256 }
2257
2258 return( err);
2259}
2260
0c530ab8
A
2261/* Routine io_service_open_ndr */
2262kern_return_t is_io_service_open_extended(
2263 io_object_t _service,
2264 task_t owningTask,
2d21ac55 2265 uint32_t connect_type,
0c530ab8
A
2266 NDR_record_t ndr,
2267 io_buf_ptr_t properties,
2268 mach_msg_type_number_t propertiesCnt,
2d21ac55 2269 kern_return_t * result,
0c530ab8
A
2270 io_object_t *connection )
2271{
2272 IOUserClient * client = 0;
2273 kern_return_t err = KERN_SUCCESS;
2274 IOReturn res = kIOReturnSuccess;
2275 OSDictionary * propertiesDict = 0;
2276 bool crossEndian;
2277 bool disallowAccess;
2278
2279 CHECK( IOService, _service, service );
2280
2281 do
2282 {
2283 if (properties)
2284 {
2285 OSObject * obj;
2286 vm_offset_t data;
2287 vm_map_offset_t map_data;
2288
2289 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2290 res = err;
2291 data = CAST_DOWN(vm_offset_t, map_data);
2292 if (KERN_SUCCESS == err)
2293 {
2294 // must return success after vm_map_copyout() succeeds
2295 obj = OSUnserializeXML( (const char *) data );
2296 vm_deallocate( kernel_map, data, propertiesCnt );
2297 propertiesDict = OSDynamicCast(OSDictionary, obj);
2298 if (!propertiesDict)
2299 {
2300 res = kIOReturnBadArgument;
2301 if (obj)
2302 obj->release();
2303 }
2304 }
2305 if (kIOReturnSuccess != res)
2306 break;
2307 }
2308
2309 crossEndian = (ndr.int_rep != NDR_record.int_rep);
2310 if (crossEndian)
2311 {
2312 if (!propertiesDict)
2313 propertiesDict = OSDictionary::withCapacity(4);
2314 OSData * data = OSData::withBytes(&ndr, sizeof(ndr));
2315 if (data)
2316 {
2317 if (propertiesDict)
2318 propertiesDict->setObject(kIOUserClientCrossEndianKey, data);
2319 data->release();
2320 }
2321 }
2322
2323 res = service->newUserClient( owningTask, (void *) owningTask,
2324 connect_type, propertiesDict, &client );
2325
2326 if (propertiesDict)
2327 propertiesDict->release();
2328
2329 if (res == kIOReturnSuccess)
2330 {
2331 assert( OSDynamicCast(IOUserClient, client) );
2332
2333 disallowAccess = (crossEndian
2334 && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
2335 && (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
2336
2337 if (disallowAccess)
2338 {
2339 client->clientClose();
2340 client->release();
2341 client = 0;
2342 res = kIOReturnUnsupported;
2343 break;
2344 }
2345 client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
2346 }
2347 }
2348 while (false);
2349
2350 *connection = client;
2351 *result = res;
2352
2353 return (err);
2354}
2355
1c79356b
A
2356/* Routine io_service_close */
2357kern_return_t is_io_service_close(
2358 io_object_t connection )
2359{
43866e37
A
2360 OSSet * mappings;
2361 if ((mappings = OSDynamicCast(OSSet, connection)))
2362 return( kIOReturnSuccess );
2363
1c79356b
A
2364 CHECK( IOUserClient, connection, client );
2365
2366 client->clientClose();
2367
2368 return( kIOReturnSuccess );
2369}
2370
2371/* Routine io_connect_get_service */
2372kern_return_t is_io_connect_get_service(
2373 io_object_t connection,
2374 io_object_t *service )
2375{
2376 IOService * theService;
2377
2378 CHECK( IOUserClient, connection, client );
2379
2380 theService = client->getService();
2381 if( theService)
2382 theService->retain();
2383
2384 *service = theService;
2385
2386 return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
2387}
2388
2389/* Routine io_connect_set_notification_port */
2390kern_return_t is_io_connect_set_notification_port(
2391 io_object_t connection,
2d21ac55 2392 uint32_t notification_type,
1c79356b 2393 mach_port_t port,
2d21ac55 2394 uint32_t reference)
1c79356b
A
2395{
2396 CHECK( IOUserClient, connection, client );
2397
2398 return( client->registerNotificationPort( port, notification_type,
2399 reference ));
2400}
2401
2d21ac55
A
2402/* Routine io_connect_set_notification_port */
2403kern_return_t is_io_connect_set_notification_port_64(
2404 io_object_t connection,
2405 uint32_t notification_type,
2406 mach_port_t port,
2407 io_user_reference_t reference)
2408{
2409 CHECK( IOUserClient, connection, client );
2410
2411 return( client->registerNotificationPort( port, notification_type,
2412 reference ));
2413}
2414
2415/* Routine io_connect_map_memory_into_task */
2416kern_return_t is_io_connect_map_memory_into_task
2417(
2418 io_connect_t connection,
2419 uint32_t memory_type,
2420 task_t into_task,
2421 mach_vm_address_t *address,
2422 mach_vm_size_t *size,
2423 uint32_t flags
2424)
1c79356b
A
2425{
2426 IOReturn err;
2427 IOMemoryMap * map;
2428
2d21ac55 2429 CHECK( IOUserClient, connection, client );
1c79356b 2430
2d21ac55 2431 map = client->mapClientMemory64( memory_type, into_task, flags, *address );
1c79356b
A
2432
2433 if( map) {
2d21ac55
A
2434 *address = map->getAddress();
2435 if( size)
2436 *size = map->getSize();
1c79356b 2437
0c530ab8 2438 if( client->sharedInstance
2d21ac55 2439 || (into_task != current_task())) {
1c79356b
A
2440 // push a name out to the task owning the map,
2441 // so we can clean up maps
2d21ac55
A
2442 mach_port_name_t name __unused =
2443 IOMachPort::makeSendRightForTask(
2444 into_task, map, IKOT_IOKIT_OBJECT );
1c79356b
A
2445 assert( name );
2446
2447 } else {
2448 // keep it with the user client
2449 IOLockLock( gIOObjectPortLock);
2450 if( 0 == client->mappings)
2451 client->mappings = OSSet::withCapacity(2);
2452 if( client->mappings)
2453 client->mappings->setObject( map);
2454 IOLockUnlock( gIOObjectPortLock);
2455 map->release();
2456 }
2457 err = kIOReturnSuccess;
2458
2459 } else
2460 err = kIOReturnBadArgument;
2461
2462 return( err );
2463}
2464
2d21ac55
A
2465/* Routine is_io_connect_map_memory */
2466kern_return_t is_io_connect_map_memory(
2467 io_object_t connect,
2468 uint32_t type,
2469 task_t task,
2470 vm_address_t * mapAddr,
2471 vm_size_t * mapSize,
2472 uint32_t flags )
2473{
2474 IOReturn err;
2475 mach_vm_address_t address;
2476 mach_vm_size_t size;
2477
2478 address = SCALAR64(*mapAddr);
2479 size = SCALAR64(*mapSize);
2480
2481 err = is_io_connect_map_memory_into_task(connect, type, task, &address, &size, flags);
2482
2483 *mapAddr = SCALAR32(address);
2484 *mapSize = SCALAR32(size);
2485
2486 return (err);
2487}
2488
483a1d10
A
2489IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
2490{
2491 OSIterator * iter;
2492 IOMemoryMap * map = 0;
2493
2494 IOLockLock(gIOObjectPortLock);
2495
2496 iter = OSCollectionIterator::withCollection(mappings);
2497 if(iter)
2498 {
2499 while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject())))
2500 {
2501 if(mem == map->getMemoryDescriptor())
2502 {
2503 map->retain();
2504 mappings->removeObject(map);
2505 break;
2506 }
2507 }
2508 iter->release();
2509 }
2510
2511 IOLockUnlock(gIOObjectPortLock);
2512
2513 return (map);
2514}
2515
2d21ac55
A
2516/* Routine io_connect_unmap_memory_from_task */
2517kern_return_t is_io_connect_unmap_memory_from_task
2518(
2519 io_connect_t connection,
2520 uint32_t memory_type,
2521 task_t from_task,
2522 mach_vm_address_t address)
1c79356b
A
2523{
2524 IOReturn err;
2525 IOOptionBits options = 0;
2526 IOMemoryDescriptor * memory;
2527 IOMemoryMap * map;
2528
2d21ac55 2529 CHECK( IOUserClient, connection, client );
1c79356b 2530
2d21ac55 2531 err = client->clientMemoryForType( (UInt32) memory_type, &options, &memory );
1c79356b
A
2532
2533 if( memory && (kIOReturnSuccess == err)) {
2534
2535 options = (options & ~kIOMapUserOptionsMask)
2536 | kIOMapAnywhere | kIOMapReference;
2537
2d21ac55 2538 map = memory->createMappingInTask( from_task, address, options );
1c79356b 2539 memory->release();
91447636
A
2540 if( map)
2541 {
1c79356b
A
2542 IOLockLock( gIOObjectPortLock);
2543 if( client->mappings)
2544 client->mappings->removeObject( map);
1c79356b 2545 IOLockUnlock( gIOObjectPortLock);
91447636
A
2546
2547 mach_port_name_t name = 0;
2d21ac55
A
2548 if (from_task != current_task())
2549 name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
91447636
A
2550 if (name)
2551 {
2552 map->unmap();
2d21ac55 2553 err = iokit_mod_send_right( from_task, name, -2 );
91447636
A
2554 err = kIOReturnSuccess;
2555 }
2556 else
2557 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
2d21ac55 2558 if (from_task == current_task())
91447636
A
2559 map->release();
2560 }
2561 else
1c79356b
A
2562 err = kIOReturnBadArgument;
2563 }
2564
2565 return( err );
2566}
2567
2d21ac55
A
2568kern_return_t is_io_connect_unmap_memory(
2569 io_object_t connect,
2570 uint32_t type,
2571 task_t task,
2572 vm_address_t mapAddr )
2573{
2574 IOReturn err;
2575 mach_vm_address_t address;
2576
2577 address = SCALAR64(mapAddr);
2578
2579 err = is_io_connect_unmap_memory_from_task(connect, type, task, mapAddr);
2580
2581 return (err);
2582}
2583
1c79356b
A
2584
2585/* Routine io_connect_add_client */
2586kern_return_t is_io_connect_add_client(
2587 io_object_t connection,
2588 io_object_t connect_to)
2589{
2590 CHECK( IOUserClient, connection, client );
2591 CHECK( IOUserClient, connect_to, to );
2592
2593 return( client->connectClient( to ) );
2594}
2595
2596
2597/* Routine io_connect_set_properties */
2598kern_return_t is_io_connect_set_properties(
2599 io_object_t connection,
2600 io_buf_ptr_t properties,
2601 mach_msg_type_number_t propertiesCnt,
2d21ac55 2602 kern_return_t * result)
1c79356b
A
2603{
2604 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
2605}
2606
2607
2d21ac55
A
2608/* Routine io_user_client_method */
2609kern_return_t is_io_connect_method
2610(
2611 io_connect_t connection,
2612 uint32_t selector,
2613 io_scalar_inband64_t scalar_input,
2614 mach_msg_type_number_t scalar_inputCnt,
2615 io_struct_inband_t inband_input,
2616 mach_msg_type_number_t inband_inputCnt,
2617 mach_vm_address_t ool_input,
2618 mach_vm_size_t ool_input_size,
2619 io_scalar_inband64_t scalar_output,
2620 mach_msg_type_number_t *scalar_outputCnt,
2621 io_struct_inband_t inband_output,
2622 mach_msg_type_number_t *inband_outputCnt,
2623 mach_vm_address_t ool_output,
2624 mach_vm_size_t * ool_output_size
2625)
1c79356b 2626{
2d21ac55 2627 CHECK( IOUserClient, connection, client );
1c79356b 2628
2d21ac55
A
2629 IOExternalMethodArguments args;
2630 IOReturn ret;
2631 IOMemoryDescriptor * inputMD = 0;
2632 IOMemoryDescriptor * outputMD = 0;
1c79356b 2633
2d21ac55
A
2634 bzero(&args.__reserved[0], sizeof(args.__reserved));
2635 args.version = kIOExternalMethodArgumentsCurrentVersion;
1c79356b 2636
2d21ac55 2637 args.selector = selector;
1c79356b 2638
2d21ac55
A
2639 args.asyncWakePort = MACH_PORT_NULL;
2640 args.asyncReference = 0;
2641 args.asyncReferenceCount = 0;
1c79356b 2642
2d21ac55
A
2643 args.scalarInput = scalar_input;
2644 args.scalarInputCount = scalar_inputCnt;
2645 args.structureInput = inband_input;
2646 args.structureInputSize = inband_inputCnt;
1c79356b 2647
2d21ac55
A
2648 if (ool_input)
2649 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2650 kIODirectionOut, current_task());
1c79356b 2651
2d21ac55 2652 args.structureInputDescriptor = inputMD;
1c79356b 2653
2d21ac55
A
2654 args.scalarOutput = scalar_output;
2655 args.scalarOutputCount = *scalar_outputCnt;
2656 args.structureOutput = inband_output;
2657 args.structureOutputSize = *inband_outputCnt;
1c79356b 2658
2d21ac55
A
2659 if (ool_output)
2660 {
2661 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
2662 kIODirectionIn, current_task());
2663 }
1c79356b 2664
2d21ac55
A
2665 args.structureOutputDescriptor = outputMD;
2666 args.structureOutputDescriptorSize = *ool_output_size;
1c79356b 2667
2d21ac55 2668 ret = client->externalMethod( selector, &args );
1c79356b 2669
2d21ac55
A
2670 *scalar_outputCnt = args.scalarOutputCount;
2671 *inband_outputCnt = args.structureOutputSize;
2672 *ool_output_size = args.structureOutputDescriptorSize;
1c79356b 2673
2d21ac55
A
2674 if (inputMD)
2675 inputMD->release();
2676 if (outputMD)
2677 outputMD->release();
1c79356b 2678
2d21ac55
A
2679 return (ret);
2680}
1c79356b 2681
2d21ac55
A
2682/* Routine io_async_user_client_method */
2683kern_return_t is_io_connect_async_method
2684(
2685 io_connect_t connection,
2686 mach_port_t wake_port,
2687 io_async_ref64_t reference,
2688 mach_msg_type_number_t referenceCnt,
2689 uint32_t selector,
2690 io_scalar_inband64_t scalar_input,
2691 mach_msg_type_number_t scalar_inputCnt,
2692 io_struct_inband_t inband_input,
2693 mach_msg_type_number_t inband_inputCnt,
2694 mach_vm_address_t ool_input,
2695 mach_vm_size_t ool_input_size,
2696 io_scalar_inband64_t scalar_output,
2697 mach_msg_type_number_t *scalar_outputCnt,
2698 io_struct_inband_t inband_output,
2699 mach_msg_type_number_t *inband_outputCnt,
2700 mach_vm_address_t ool_output,
2701 mach_vm_size_t * ool_output_size
2702)
2703{
2704 CHECK( IOUserClient, connection, client );
1c79356b 2705
2d21ac55
A
2706 IOExternalMethodArguments args;
2707 IOReturn ret;
2708 IOMemoryDescriptor * inputMD = 0;
2709 IOMemoryDescriptor * outputMD = 0;
2710
2711 bzero(&args.__reserved[0], sizeof(args.__reserved));
2712 args.version = kIOExternalMethodArgumentsCurrentVersion;
2713
2714 reference[0] = (io_user_reference_t) wake_port;
2715 if (vm_map_is_64bit(get_task_map(current_task())))
2716 reference[0] |= kIOUCAsync64Flag;
2717
2718 args.selector = selector;
2719
2720 args.asyncWakePort = wake_port;
2721 args.asyncReference = reference;
2722 args.asyncReferenceCount = referenceCnt;
2723
2724 args.scalarInput = scalar_input;
2725 args.scalarInputCount = scalar_inputCnt;
2726 args.structureInput = inband_input;
2727 args.structureInputSize = inband_inputCnt;
2728
2729 if (ool_input)
2730 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2731 kIODirectionOut, current_task());
2732
2733 args.structureInputDescriptor = inputMD;
2734
2735 args.scalarOutput = scalar_output;
2736 args.scalarOutputCount = *scalar_outputCnt;
2737 args.structureOutput = inband_output;
2738 args.structureOutputSize = *inband_outputCnt;
2739
2740 if (ool_output)
2741 {
2742 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
2743 kIODirectionIn, current_task());
2744 }
2745
2746 args.structureOutputDescriptor = outputMD;
2747 args.structureOutputDescriptorSize = *ool_output_size;
2748
2749 ret = client->externalMethod( selector, &args );
2750
2751 *inband_outputCnt = args.structureOutputSize;
2752 *ool_output_size = args.structureOutputDescriptorSize;
2753
2754 if (inputMD)
2755 inputMD->release();
2756 if (outputMD)
2757 outputMD->release();
2758
2759 return (ret);
1c79356b
A
2760}
2761
2d21ac55
A
2762/* Routine io_connect_method_scalarI_scalarO */
2763kern_return_t is_io_connect_method_scalarI_scalarO(
2764 io_object_t connect,
2765 uint32_t index,
2766 io_scalar_inband_t input,
2767 mach_msg_type_number_t inputCount,
2768 io_scalar_inband_t output,
2769 mach_msg_type_number_t * outputCount )
2770{
2771 IOReturn err;
2772 uint32_t i;
2773 io_scalar_inband64_t _input;
2774 io_scalar_inband64_t _output;
2775
2776 mach_msg_type_number_t struct_outputCnt = 0;
2777 mach_vm_size_t ool_output_size = 0;
2778
2779 for (i = 0; i < inputCount; i++)
2780 _input[i] = SCALAR64(input[i]);
2781
2782 err = is_io_connect_method(connect, index,
2783 _input, inputCount,
2784 NULL, 0,
2785 0, 0,
2786 _output, outputCount,
2787 NULL, &struct_outputCnt,
2788 0, &ool_output_size);
2789
2790 for (i = 0; i < *outputCount; i++)
2791 output[i] = SCALAR32(_output[i]);
2792
2793 return (err);
2794}
2795
2796kern_return_t shim_io_connect_method_scalarI_scalarO(
2797 IOExternalMethod * method,
2798 IOService * object,
2799 const io_user_scalar_t * input,
2800 mach_msg_type_number_t inputCount,
2801 io_user_scalar_t * output,
2802 mach_msg_type_number_t * outputCount )
1c79356b 2803{
1c79356b 2804 IOMethod func;
2d21ac55
A
2805 io_scalar_inband_t _output;
2806 IOReturn err;
2807 err = kIOReturnBadArgument;
1c79356b 2808
2d21ac55 2809 do {
1c79356b 2810
2d21ac55
A
2811 if( inputCount != method->count0)
2812 {
2813 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
1c79356b 2814 continue;
2d21ac55
A
2815 }
2816 if( *outputCount != method->count1)
2817 {
2818 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
1c79356b 2819 continue;
2d21ac55 2820 }
1c79356b
A
2821
2822 func = method->func;
2823
2824 switch( inputCount) {
2825
2d21ac55
A
2826 case 6:
2827 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
2828 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
2829 break;
1c79356b 2830 case 5:
2d21ac55
A
2831 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
2832 ARG32(input[3]), ARG32(input[4]),
2833 &_output[0] );
1c79356b
A
2834 break;
2835 case 4:
2d21ac55
A
2836 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
2837 ARG32(input[3]),
2838 &_output[0], &_output[1] );
1c79356b
A
2839 break;
2840 case 3:
2d21ac55
A
2841 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
2842 &_output[0], &_output[1], &_output[2] );
1c79356b
A
2843 break;
2844 case 2:
2d21ac55
A
2845 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
2846 &_output[0], &_output[1], &_output[2],
2847 &_output[3] );
1c79356b
A
2848 break;
2849 case 1:
2d21ac55
A
2850 err = (object->*func)( ARG32(input[0]),
2851 &_output[0], &_output[1], &_output[2],
2852 &_output[3], &_output[4] );
1c79356b
A
2853 break;
2854 case 0:
2d21ac55
A
2855 err = (object->*func)( &_output[0], &_output[1], &_output[2],
2856 &_output[3], &_output[4], &_output[5] );
1c79356b
A
2857 break;
2858
2859 default:
2d21ac55 2860 IOLog("%s: Bad method table\n", object->getName());
1c79356b 2861 }
2d21ac55
A
2862 }
2863 while( false);
1c79356b 2864
2d21ac55
A
2865 uint32_t i;
2866 for (i = 0; i < *outputCount; i++)
2867 output[i] = SCALAR32(_output[i]);
1c79356b
A
2868
2869 return( err);
2870}
2871
2d21ac55
A
2872/* Routine io_async_method_scalarI_scalarO */
2873kern_return_t is_io_async_method_scalarI_scalarO(
2874 io_object_t connect,
2875 mach_port_t wake_port,
2876 io_async_ref_t reference,
2877 mach_msg_type_number_t referenceCnt,
2878 uint32_t index,
2879 io_scalar_inband_t input,
2880 mach_msg_type_number_t inputCount,
2881 io_scalar_inband_t output,
2882 mach_msg_type_number_t * outputCount )
2883{
2884 IOReturn err;
2885 uint32_t i;
2886 io_scalar_inband64_t _input;
2887 io_scalar_inband64_t _output;
2888 io_async_ref64_t _reference;
2889
2890 for (i = 0; i < referenceCnt; i++)
2891 _reference[i] = REF64(reference[i]);
2892
2893 mach_msg_type_number_t struct_outputCnt = 0;
2894 mach_vm_size_t ool_output_size = 0;
2895
2896 for (i = 0; i < inputCount; i++)
2897 _input[i] = SCALAR64(input[i]);
2898
2899 err = is_io_connect_async_method(connect,
2900 wake_port, _reference, referenceCnt,
2901 index,
2902 _input, inputCount,
2903 NULL, 0,
2904 0, 0,
2905 _output, outputCount,
2906 NULL, &struct_outputCnt,
2907 0, &ool_output_size);
2908
2909 for (i = 0; i < *outputCount; i++)
2910 output[i] = SCALAR32(_output[i]);
2911
2912 return (err);
2913}
2914/* Routine io_async_method_scalarI_structureO */
2915kern_return_t is_io_async_method_scalarI_structureO(
1c79356b 2916 io_object_t connect,
2d21ac55
A
2917 mach_port_t wake_port,
2918 io_async_ref_t reference,
2919 mach_msg_type_number_t referenceCnt,
2920 uint32_t index,
2921 io_scalar_inband_t input,
2922 mach_msg_type_number_t inputCount,
2923 io_struct_inband_t output,
2924 mach_msg_type_number_t * outputCount )
1c79356b 2925{
2d21ac55
A
2926 uint32_t i;
2927 io_scalar_inband64_t _input;
2928 io_async_ref64_t _reference;
1c79356b 2929
2d21ac55
A
2930 for (i = 0; i < referenceCnt; i++)
2931 _reference[i] = REF64(reference[i]);
1c79356b 2932
2d21ac55
A
2933 mach_msg_type_number_t scalar_outputCnt = 0;
2934 mach_vm_size_t ool_output_size = 0;
1c79356b 2935
2d21ac55
A
2936 for (i = 0; i < inputCount; i++)
2937 _input[i] = SCALAR64(input[i]);
2938
2939 return (is_io_connect_async_method(connect,
2940 wake_port, _reference, referenceCnt,
2941 index,
2942 _input, inputCount,
2943 NULL, 0,
2944 0, 0,
2945 NULL, &scalar_outputCnt,
2946 output, outputCount,
2947 0, &ool_output_size));
2948}
1c79356b 2949
2d21ac55
A
2950/* Routine io_async_method_scalarI_structureI */
2951kern_return_t is_io_async_method_scalarI_structureI(
2952 io_connect_t connect,
2953 mach_port_t wake_port,
2954 io_async_ref_t reference,
2955 mach_msg_type_number_t referenceCnt,
2956 uint32_t index,
2957 io_scalar_inband_t input,
2958 mach_msg_type_number_t inputCount,
2959 io_struct_inband_t inputStruct,
2960 mach_msg_type_number_t inputStructCount )
2961{
2962 uint32_t i;
2963 io_scalar_inband64_t _input;
2964 io_async_ref64_t _reference;
1c79356b 2965
2d21ac55
A
2966 for (i = 0; i < referenceCnt; i++)
2967 _reference[i] = REF64(reference[i]);
1c79356b 2968
2d21ac55
A
2969 mach_msg_type_number_t scalar_outputCnt = 0;
2970 mach_msg_type_number_t inband_outputCnt = 0;
2971 mach_vm_size_t ool_output_size = 0;
1c79356b 2972
2d21ac55
A
2973 for (i = 0; i < inputCount; i++)
2974 _input[i] = SCALAR64(input[i]);
2975
2976 return (is_io_connect_async_method(connect,
2977 wake_port, _reference, referenceCnt,
2978 index,
2979 _input, inputCount,
2980 inputStruct, inputStructCount,
2981 0, 0,
2982 NULL, &scalar_outputCnt,
2983 NULL, &inband_outputCnt,
2984 0, &ool_output_size));
1c79356b
A
2985}
2986
2d21ac55
A
2987/* Routine io_async_method_structureI_structureO */
2988kern_return_t is_io_async_method_structureI_structureO(
2989 io_object_t connect,
2990 mach_port_t wake_port,
2991 io_async_ref_t reference,
2992 mach_msg_type_number_t referenceCnt,
2993 uint32_t index,
2994 io_struct_inband_t input,
2995 mach_msg_type_number_t inputCount,
2996 io_struct_inband_t output,
2997 mach_msg_type_number_t * outputCount )
2998{
2999 uint32_t i;
3000 mach_msg_type_number_t scalar_outputCnt = 0;
3001 mach_vm_size_t ool_output_size = 0;
3002 io_async_ref64_t _reference;
3003
3004 for (i = 0; i < referenceCnt; i++)
3005 _reference[i] = REF64(reference[i]);
3006
3007 return (is_io_connect_async_method(connect,
3008 wake_port, _reference, referenceCnt,
3009 index,
3010 NULL, 0,
3011 input, inputCount,
3012 0, 0,
3013 NULL, &scalar_outputCnt,
3014 output, outputCount,
3015 0, &ool_output_size));
3016}
3017
3018
3019kern_return_t shim_io_async_method_scalarI_scalarO(
3020 IOExternalAsyncMethod * method,
3021 IOService * object,
3022 mach_port_t asyncWakePort,
3023 io_user_reference_t * asyncReference,
3024 uint32_t asyncReferenceCount,
3025 const io_user_scalar_t * input,
3026 mach_msg_type_number_t inputCount,
3027 io_user_scalar_t * output,
3028 mach_msg_type_number_t * outputCount )
1c79356b 3029{
1c79356b 3030 IOAsyncMethod func;
2d21ac55
A
3031 uint32_t i;
3032 io_scalar_inband_t _output;
3033 IOReturn err;
3034 io_async_ref_t reference;
1c79356b 3035
2d21ac55
A
3036 for (i = 0; i < asyncReferenceCount; i++)
3037 reference[i] = REF32(asyncReference[i]);
1c79356b 3038
2d21ac55
A
3039 err = kIOReturnBadArgument;
3040
3041 do {
3042
3043 if( inputCount != method->count0)
3044 {
3045 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3046 continue;
3047 }
3048 if( *outputCount != method->count1)
3049 {
3050 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3051 continue;
3052 }
3053
3054 func = method->func;
1c79356b
A
3055
3056 switch( inputCount) {
3057
3058 case 6:
3059 err = (object->*func)( reference,
2d21ac55
A
3060 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3061 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
1c79356b
A
3062 break;
3063 case 5:
3064 err = (object->*func)( reference,
2d21ac55
A
3065 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3066 ARG32(input[3]), ARG32(input[4]),
3067 &_output[0] );
1c79356b
A
3068 break;
3069 case 4:
3070 err = (object->*func)( reference,
2d21ac55
A
3071 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3072 ARG32(input[3]),
3073 &_output[0], &_output[1] );
1c79356b
A
3074 break;
3075 case 3:
3076 err = (object->*func)( reference,
2d21ac55
A
3077 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3078 &_output[0], &_output[1], &_output[2] );
1c79356b
A
3079 break;
3080 case 2:
3081 err = (object->*func)( reference,
2d21ac55
A
3082 ARG32(input[0]), ARG32(input[1]),
3083 &_output[0], &_output[1], &_output[2],
3084 &_output[3] );
1c79356b
A
3085 break;
3086 case 1:
3087 err = (object->*func)( reference,
2d21ac55
A
3088 ARG32(input[0]),
3089 &_output[0], &_output[1], &_output[2],
3090 &_output[3], &_output[4] );
1c79356b
A
3091 break;
3092 case 0:
3093 err = (object->*func)( reference,
2d21ac55
A
3094 &_output[0], &_output[1], &_output[2],
3095 &_output[3], &_output[4], &_output[5] );
1c79356b
A
3096 break;
3097
3098 default:
2d21ac55 3099 IOLog("%s: Bad method table\n", object->getName());
1c79356b 3100 }
2d21ac55
A
3101 }
3102 while( false);
1c79356b 3103
2d21ac55
A
3104 for (i = 0; i < *outputCount; i++)
3105 output[i] = SCALAR32(_output[i]);
1c79356b
A
3106
3107 return( err);
3108}
3109
2d21ac55
A
3110
3111/* Routine io_connect_method_scalarI_structureO */
3112kern_return_t is_io_connect_method_scalarI_structureO(
3113 io_object_t connect,
3114 uint32_t index,
3115 io_scalar_inband_t input,
3116 mach_msg_type_number_t inputCount,
3117 io_struct_inband_t output,
3118 mach_msg_type_number_t * outputCount )
1c79356b 3119{
2d21ac55
A
3120 uint32_t i;
3121 io_scalar_inband64_t _input;
3122
3123 mach_msg_type_number_t scalar_outputCnt = 0;
3124 mach_vm_size_t ool_output_size = 0;
3125
3126 for (i = 0; i < inputCount; i++)
3127 _input[i] = SCALAR64(input[i]);
3128
3129 return (is_io_connect_method(connect, index,
3130 _input, inputCount,
3131 NULL, 0,
3132 0, 0,
3133 NULL, &scalar_outputCnt,
3134 output, outputCount,
3135 0, &ool_output_size));
3136}
3137
3138kern_return_t shim_io_connect_method_scalarI_structureO(
3139
3140 IOExternalMethod * method,
3141 IOService * object,
3142 const io_user_scalar_t * input,
3143 mach_msg_type_number_t inputCount,
3144 io_struct_inband_t output,
3145 mach_msg_type_number_t * outputCount )
3146{
3147 IOMethod func;
1c79356b 3148 IOReturn err;
2d21ac55
A
3149
3150 err = kIOReturnBadArgument;
3151
3152 do {
3153 if( inputCount != method->count0)
3154 {
3155 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3156 continue;
3157 }
3158 if( (kIOUCVariableStructureSize != method->count1)
3159 && (*outputCount != method->count1))
3160 {
3161 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3162 continue;
3163 }
3164
3165 func = method->func;
3166
3167 switch( inputCount) {
3168
3169 case 5:
3170 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3171 ARG32(input[3]), ARG32(input[4]),
3172 output );
3173 break;
3174 case 4:
3175 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3176 ARG32(input[3]),
3177 output, (void *)outputCount );
3178 break;
3179 case 3:
3180 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3181 output, (void *)outputCount, 0 );
3182 break;
3183 case 2:
3184 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3185 output, (void *)outputCount, 0, 0 );
3186 break;
3187 case 1:
3188 err = (object->*func)( ARG32(input[0]),
3189 output, (void *)outputCount, 0, 0, 0 );
3190 break;
3191 case 0:
3192 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 );
3193 break;
3194
3195 default:
3196 IOLog("%s: Bad method table\n", object->getName());
3197 }
3198 }
3199 while( false);
3200
3201 return( err);
3202}
3203
3204
3205kern_return_t shim_io_async_method_scalarI_structureO(
3206 IOExternalAsyncMethod * method,
3207 IOService * object,
3208 mach_port_t asyncWakePort,
3209 io_user_reference_t * asyncReference,
3210 uint32_t asyncReferenceCount,
3211 const io_user_scalar_t * input,
3212 mach_msg_type_number_t inputCount,
3213 io_struct_inband_t output,
3214 mach_msg_type_number_t * outputCount )
3215{
1c79356b 3216 IOAsyncMethod func;
2d21ac55
A
3217 uint32_t i;
3218 IOReturn err;
3219 io_async_ref_t reference;
1c79356b 3220
2d21ac55
A
3221 for (i = 0; i < asyncReferenceCount; i++)
3222 reference[i] = REF32(asyncReference[i]);
1c79356b 3223
2d21ac55
A
3224 err = kIOReturnBadArgument;
3225 do {
3226 if( inputCount != method->count0)
3227 {
3228 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3229 continue;
3230 }
3231 if( (kIOUCVariableStructureSize != method->count1)
3232 && (*outputCount != method->count1))
3233 {
3234 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3235 continue;
3236 }
1c79356b 3237
2d21ac55 3238 func = method->func;
1c79356b
A
3239
3240 switch( inputCount) {
3241
3242 case 5:
3243 err = (object->*func)( reference,
2d21ac55
A
3244 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3245 ARG32(input[3]), ARG32(input[4]),
1c79356b
A
3246 output );
3247 break;
3248 case 4:
3249 err = (object->*func)( reference,
2d21ac55
A
3250 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3251 ARG32(input[3]),
1c79356b
A
3252 output, (void *)outputCount );
3253 break;
3254 case 3:
3255 err = (object->*func)( reference,
2d21ac55 3256 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
1c79356b
A
3257 output, (void *)outputCount, 0 );
3258 break;
3259 case 2:
3260 err = (object->*func)( reference,
2d21ac55 3261 ARG32(input[0]), ARG32(input[1]),
1c79356b
A
3262 output, (void *)outputCount, 0, 0 );
3263 break;
3264 case 1:
3265 err = (object->*func)( reference,
2d21ac55 3266 ARG32(input[0]),
1c79356b
A
3267 output, (void *)outputCount, 0, 0, 0 );
3268 break;
3269 case 0:
3270 err = (object->*func)( reference,
3271 output, (void *)outputCount, 0, 0, 0, 0 );
3272 break;
3273
3274 default:
2d21ac55 3275 IOLog("%s: Bad method table\n", object->getName());
1c79356b 3276 }
2d21ac55
A
3277 }
3278 while( false);
1c79356b 3279
2d21ac55
A
3280 return( err);
3281}
3282
3283/* Routine io_connect_method_scalarI_structureI */
3284kern_return_t is_io_connect_method_scalarI_structureI(
3285 io_connect_t connect,
3286 uint32_t index,
3287 io_scalar_inband_t input,
3288 mach_msg_type_number_t inputCount,
3289 io_struct_inband_t inputStruct,
3290 mach_msg_type_number_t inputStructCount )
3291{
3292 uint32_t i;
3293 io_scalar_inband64_t _input;
3294
3295 mach_msg_type_number_t scalar_outputCnt = 0;
3296 mach_msg_type_number_t inband_outputCnt = 0;
3297 mach_vm_size_t ool_output_size = 0;
3298
3299 for (i = 0; i < inputCount; i++)
3300 _input[i] = SCALAR64(input[i]);
3301
3302 return (is_io_connect_method(connect, index,
3303 _input, inputCount,
3304 inputStruct, inputStructCount,
3305 0, 0,
3306 NULL, &scalar_outputCnt,
3307 NULL, &inband_outputCnt,
3308 0, &ool_output_size));
3309}
3310
3311kern_return_t shim_io_connect_method_scalarI_structureI(
3312 IOExternalMethod * method,
3313 IOService * object,
3314 const io_user_scalar_t * input,
3315 mach_msg_type_number_t inputCount,
3316 io_struct_inband_t inputStruct,
3317 mach_msg_type_number_t inputStructCount )
3318{
3319 IOMethod func;
3320 IOReturn err = kIOReturnBadArgument;
3321
3322 do
3323 {
3324 if( (kIOUCVariableStructureSize != method->count0)
3325 && (inputCount != method->count0))
3326 {
3327 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3328 continue;
3329 }
3330 if( (kIOUCVariableStructureSize != method->count1)
3331 && (inputStructCount != method->count1))
3332 {
3333 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3334 continue;
3335 }
3336
3337 func = method->func;
3338
3339 switch( inputCount) {
3340
3341 case 5:
3342 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3343 ARG32(input[3]), ARG32(input[4]),
3344 inputStruct );
3345 break;
3346 case 4:
3347 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *) input[2],
3348 ARG32(input[3]),
3349 inputStruct, (void *)inputStructCount );
3350 break;
3351 case 3:
3352 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3353 inputStruct, (void *)inputStructCount,
3354 0 );
3355 break;
3356 case 2:
3357 err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3358 inputStruct, (void *)inputStructCount,
3359 0, 0 );
3360 break;
3361 case 1:
3362 err = (object->*func)( ARG32(input[0]),
3363 inputStruct, (void *)inputStructCount,
3364 0, 0, 0 );
3365 break;
3366 case 0:
3367 err = (object->*func)( inputStruct, (void *)inputStructCount,
3368 0, 0, 0, 0 );
3369 break;
3370
3371 default:
3372 IOLog("%s: Bad method table\n", object->getName());
3373 }
3374 }
3375 while (false);
1c79356b
A
3376
3377 return( err);
3378}
3379
2d21ac55
A
3380kern_return_t shim_io_async_method_scalarI_structureI(
3381 IOExternalAsyncMethod * method,
3382 IOService * object,
3383 mach_port_t asyncWakePort,
3384 io_user_reference_t * asyncReference,
3385 uint32_t asyncReferenceCount,
3386 const io_user_scalar_t * input,
3387 mach_msg_type_number_t inputCount,
3388 io_struct_inband_t inputStruct,
3389 mach_msg_type_number_t inputStructCount )
1c79356b 3390{
1c79356b 3391 IOAsyncMethod func;
2d21ac55
A
3392 uint32_t i;
3393 IOReturn err = kIOReturnBadArgument;
3394 io_async_ref_t reference;
1c79356b 3395
2d21ac55
A
3396 for (i = 0; i < asyncReferenceCount; i++)
3397 reference[i] = REF32(asyncReference[i]);
1c79356b 3398
2d21ac55
A
3399 do
3400 {
3401 if( (kIOUCVariableStructureSize != method->count0)
3402 && (inputCount != method->count0))
3403 {
3404 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3405 continue;
3406 }
3407 if( (kIOUCVariableStructureSize != method->count1)
3408 && (inputStructCount != method->count1))
3409 {
3410 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3411 continue;
3412 }
1c79356b 3413
1c79356b
A
3414 func = method->func;
3415
3416 switch( inputCount) {
3417
3418 case 5:
3419 err = (object->*func)( reference,
2d21ac55
A
3420 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3421 ARG32(input[3]), ARG32(input[4]),
1c79356b
A
3422 inputStruct );
3423 break;
3424 case 4:
3425 err = (object->*func)( reference,
2d21ac55
A
3426 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3427 ARG32(input[3]),
1c79356b
A
3428 inputStruct, (void *)inputStructCount );
3429 break;
3430 case 3:
3431 err = (object->*func)( reference,
2d21ac55 3432 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
1c79356b
A
3433 inputStruct, (void *)inputStructCount,
3434 0 );
3435 break;
3436 case 2:
3437 err = (object->*func)( reference,
2d21ac55 3438 ARG32(input[0]), ARG32(input[1]),
1c79356b
A
3439 inputStruct, (void *)inputStructCount,
3440 0, 0 );
3441 break;
3442 case 1:
3443 err = (object->*func)( reference,
2d21ac55 3444 ARG32(input[0]),
1c79356b
A
3445 inputStruct, (void *)inputStructCount,
3446 0, 0, 0 );
3447 break;
3448 case 0:
3449 err = (object->*func)( reference,
3450 inputStruct, (void *)inputStructCount,
3451 0, 0, 0, 0 );
3452 break;
3453
3454 default:
2d21ac55 3455 IOLog("%s: Bad method table\n", object->getName());
1c79356b 3456 }
2d21ac55
A
3457 }
3458 while (false);
3459
3460 return( err);
3461}
3462
3463/* Routine io_connect_method_structureI_structureO */
3464kern_return_t is_io_connect_method_structureI_structureO(
3465 io_object_t connect,
3466 uint32_t index,
3467 io_struct_inband_t input,
3468 mach_msg_type_number_t inputCount,
3469 io_struct_inband_t output,
3470 mach_msg_type_number_t * outputCount )
3471{
3472 mach_msg_type_number_t scalar_outputCnt = 0;
3473 mach_vm_size_t ool_output_size = 0;
3474
3475 return (is_io_connect_method(connect, index,
3476 NULL, 0,
3477 input, inputCount,
3478 0, 0,
3479 NULL, &scalar_outputCnt,
3480 output, outputCount,
3481 0, &ool_output_size));
3482}
3483
3484kern_return_t shim_io_connect_method_structureI_structureO(
3485 IOExternalMethod * method,
3486 IOService * object,
3487 io_struct_inband_t input,
3488 mach_msg_type_number_t inputCount,
3489 io_struct_inband_t output,
3490 mach_msg_type_number_t * outputCount )
3491{
3492 IOMethod func;
3493 IOReturn err = kIOReturnBadArgument;
3494
3495 do
3496 {
3497 if( (kIOUCVariableStructureSize != method->count0)
3498 && (inputCount != method->count0))
3499 {
3500 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3501 continue;
3502 }
3503 if( (kIOUCVariableStructureSize != method->count1)
3504 && (*outputCount != method->count1))
3505 {
3506 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3507 continue;
3508 }
3509
3510 func = method->func;
3511
3512 if( method->count1) {
3513 if( method->count0) {
3514 err = (object->*func)( input, output,
3515 (void *)inputCount, outputCount, 0, 0 );
3516 } else {
3517 err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
3518 }
3519 } else {
3520 err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
3521 }
3522 }
3523 while( false);
1c79356b 3524
1c79356b
A
3525
3526 return( err);
3527}
3528
2d21ac55
A
3529kern_return_t shim_io_async_method_structureI_structureO(
3530 IOExternalAsyncMethod * method,
3531 IOService * object,
3532 mach_port_t asyncWakePort,
3533 io_user_reference_t * asyncReference,
3534 uint32_t asyncReferenceCount,
3535 io_struct_inband_t input,
3536 mach_msg_type_number_t inputCount,
3537 io_struct_inband_t output,
3538 mach_msg_type_number_t * outputCount )
1c79356b 3539{
1c79356b 3540 IOAsyncMethod func;
2d21ac55
A
3541 uint32_t i;
3542 IOReturn err;
3543 io_async_ref_t reference;
1c79356b 3544
2d21ac55
A
3545 for (i = 0; i < asyncReferenceCount; i++)
3546 reference[i] = REF32(asyncReference[i]);
1c79356b 3547
2d21ac55
A
3548 err = kIOReturnBadArgument;
3549 do
3550 {
3551 if( (kIOUCVariableStructureSize != method->count0)
3552 && (inputCount != method->count0))
3553 {
3554 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3555 continue;
3556 }
3557 if( (kIOUCVariableStructureSize != method->count1)
3558 && (*outputCount != method->count1))
3559 {
3560 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3561 continue;
3562 }
1c79356b 3563
1c79356b
A
3564 func = method->func;
3565
3566 if( method->count1) {
3567 if( method->count0) {
3568 err = (object->*func)( reference,
3569 input, output,
3570 (void *)inputCount, outputCount, 0, 0 );
3571 } else {
3572 err = (object->*func)( reference,
3573 output, outputCount, 0, 0, 0, 0 );
3574 }
3575 } else {
3576 err = (object->*func)( reference,
3577 input, (void *)inputCount, 0, 0, 0, 0 );
3578 }
2d21ac55
A
3579 }
3580 while( false);
1c79356b
A
3581
3582 return( err);
3583}
2d21ac55 3584
1c79356b
A
3585/* Routine io_make_matching */
3586kern_return_t is_io_make_matching(
2d21ac55
A
3587 mach_port_t master_port,
3588 uint32_t type,
3589 uint32_t options,
3590 io_struct_inband_t input,
3591 mach_msg_type_number_t inputCount,
1c79356b
A
3592 io_string_t matching )
3593{
3594 OSSerialize * s;
3595 IOReturn err = kIOReturnSuccess;
3596 OSDictionary * dict;
3597
3598 if( master_port != master_device_port)
3599 return( kIOReturnNotPrivileged);
3600
3601 switch( type) {
3602
3603 case kIOServiceMatching:
3604 dict = IOService::serviceMatching( gIOServiceKey );
3605 break;
3606
3607 case kIOBSDNameMatching:
3608 dict = IOBSDNameMatching( (const char *) input );
3609 break;
3610
3611 case kIOOFPathMatching:
3612 dict = IOOFPathMatching( (const char *) input,
3613 matching, sizeof( io_string_t));
3614 break;
3615
3616 default:
3617 dict = 0;
3618 }
3619
3620 if( !dict)
3621 return( kIOReturnUnsupported);
3622
3623 do {
3624 s = OSSerialize::withCapacity(4096);
3625 if( !s) {
3626 err = kIOReturnNoMemory;
3627 continue;
3628 }
3629 s->clearText();
3630 if( !dict->serialize( s )) {
3631 err = kIOReturnUnsupported;
3632 continue;
3633 }
3634
3635 if( s->getLength() > sizeof( io_string_t)) {
3636 err = kIOReturnNoMemory;
3637 continue;
3638 } else
3639 strcpy( matching, s->text());
2d21ac55
A
3640 }
3641 while( false);
1c79356b
A
3642
3643 if( s)
3644 s->release();
3645 if( dict)
3646 dict->release();
3647
3648 return( err);
3649}
3650
3651/* Routine io_catalog_send_data */
3652kern_return_t is_io_catalog_send_data(
3653 mach_port_t master_port,
2d21ac55 3654 uint32_t flag,
1c79356b
A
3655 io_buf_ptr_t inData,
3656 mach_msg_type_number_t inDataCount,
2d21ac55 3657 kern_return_t * result)
1c79356b
A
3658{
3659 OSObject * obj = 0;
3660 vm_offset_t data;
3661 kern_return_t kr = kIOReturnError;
3662
3663 //printf("io_catalog_send_data called. flag: %d\n", flag);
3664
3665 if( master_port != master_device_port)
3666 return kIOReturnNotPrivileged;
3667
3668 // FIXME: This is a hack. Should have own function for removeKernelLinker()
2d21ac55 3669 if( (flag != kIOCatalogRemoveKernelLinker && flag != kIOCatalogKextdFinishedLaunching) && ( !inData || !inDataCount) )
1c79356b
A
3670 return kIOReturnBadArgument;
3671
91447636
A
3672 if (inData) {
3673 vm_map_offset_t map_data;
3674
3675 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
3676 data = CAST_DOWN(vm_offset_t, map_data);
3677
1c79356b
A
3678 if( kr != KERN_SUCCESS)
3679 return kr;
3680
3681 // must return success after vm_map_copyout() succeeds
3682
3683 if( inDataCount ) {
3684 obj = (OSObject *)OSUnserializeXML((const char *)data);
3685 vm_deallocate( kernel_map, data, inDataCount );
3686 if( !obj) {
3687 *result = kIOReturnNoMemory;
3688 return( KERN_SUCCESS);
3689 }
3690 }
3691 }
3692
3693 switch ( flag ) {
3694 case kIOCatalogAddDrivers:
3695 case kIOCatalogAddDriversNoMatch: {
3696 OSArray * array;
3697
3698 array = OSDynamicCast(OSArray, obj);
3699 if ( array ) {
1c79356b
A
3700 if ( !gIOCatalogue->addDrivers( array ,
3701 flag == kIOCatalogAddDrivers) ) {
3702 kr = kIOReturnError;
3703 }
3704 }
3705 else {
3706 kr = kIOReturnBadArgument;
3707 }
3708 }
3709 break;
3710
3711 case kIOCatalogRemoveDrivers:
3712 case kIOCatalogRemoveDriversNoMatch: {
3713 OSDictionary * dict;
3714
3715 dict = OSDynamicCast(OSDictionary, obj);
3716 if ( dict ) {
1c79356b
A
3717 if ( !gIOCatalogue->removeDrivers( dict,
3718 flag == kIOCatalogRemoveDrivers ) ) {
3719 kr = kIOReturnError;
3720 }
3721 }
3722 else {
3723 kr = kIOReturnBadArgument;
3724 }
3725 }
3726 break;
3727
3728 case kIOCatalogStartMatching: {
3729 OSDictionary * dict;
3730
3731 dict = OSDynamicCast(OSDictionary, obj);
3732 if ( dict ) {
1c79356b
A
3733 if ( !gIOCatalogue->startMatching( dict ) ) {
3734 kr = kIOReturnError;
3735 }
3736 }
3737 else {
3738 kr = kIOReturnBadArgument;
3739 }
3740 }
3741 break;
3742
3743 case kIOCatalogRemoveKernelLinker: {
3744 if (gIOCatalogue->removeKernelLinker() != KERN_SUCCESS) {
3745 kr = kIOReturnError;
9bccf70c
A
3746 } else {
3747 kr = kIOReturnSuccess;
1c79356b
A
3748 }
3749 }
3750 break;
3751
2d21ac55
A
3752 case kIOCatalogKextdFinishedLaunching: {
3753#if !NO_KEXTD
3754 static bool clearedBusy = false;
3755 if (!clearedBusy) {
3756 IOService * serviceRoot = IOService::getServiceRoot();
3757 if (serviceRoot) {
3758 serviceRoot->adjustBusy(-1);
3759 clearedBusy = true;
3760 }
3761 }
3762#endif
3763 kr = kIOReturnSuccess;
3764 }
3765 break;
3766
1c79356b
A
3767 default:
3768 kr = kIOReturnBadArgument;
3769 break;
3770 }
3771
3772 if (obj) obj->release();
3773
3774 *result = kr;
3775 return( KERN_SUCCESS);
3776}
3777
3778/* Routine io_catalog_terminate */
3779kern_return_t is_io_catalog_terminate(
3780 mach_port_t master_port,
2d21ac55 3781 uint32_t flag,
1c79356b
A
3782 io_name_t name )
3783{
3784 kern_return_t kr;
3785
3786 if( master_port != master_device_port )
3787 return kIOReturnNotPrivileged;
3788
3789 kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
3790 kIOClientPrivilegeAdministrator );
3791 if( kIOReturnSuccess != kr)
3792 return( kr );
3793
3794 switch ( flag ) {
3795 case kIOCatalogServiceTerminate:
3796 OSIterator * iter;
3797 IOService * service;
3798
3799 iter = IORegistryIterator::iterateOver(gIOServicePlane,
3800 kIORegistryIterateRecursively);
3801 if ( !iter )
3802 return kIOReturnNoMemory;
3803
3804 do {
3805 iter->reset();
3806 while( (service = (IOService *)iter->getNextObject()) ) {
3807 if( service->metaCast(name)) {
3808 if ( !service->terminate( kIOServiceRequired
3809 | kIOServiceSynchronous) ) {
3810 kr = kIOReturnUnsupported;
3811 break;
3812 }
3813 }
3814 }
3815 } while( !service && !iter->isValid());
3816 iter->release();
3817 break;
3818
3819 case kIOCatalogModuleUnload:
3820 case kIOCatalogModuleTerminate:
3821 kr = gIOCatalogue->terminateDriversForModule(name,
3822 flag == kIOCatalogModuleUnload);
3823 break;
3824
3825 default:
3826 kr = kIOReturnBadArgument;
3827 break;
3828 }
3829
3830 return( kr );
3831}
3832
3833/* Routine io_catalog_get_data */
3834kern_return_t is_io_catalog_get_data(
3835 mach_port_t master_port,
2d21ac55 3836 uint32_t flag,
1c79356b
A
3837 io_buf_ptr_t *outData,
3838 mach_msg_type_number_t *outDataCount)
3839{
3840 kern_return_t kr = kIOReturnSuccess;
3841 OSSerialize * s;
3842
3843 if( master_port != master_device_port)
3844 return kIOReturnNotPrivileged;
3845
3846 //printf("io_catalog_get_data called. flag: %d\n", flag);
3847
3848 s = OSSerialize::withCapacity(4096);
3849 if ( !s )
3850 return kIOReturnNoMemory;
3851
3852 s->clearText();
1c79356b 3853
55e303ae 3854 kr = gIOCatalogue->serializeData(flag, s);
1c79356b
A
3855
3856 if ( kr == kIOReturnSuccess ) {
3857 vm_offset_t data;
3858 vm_map_copy_t copy;
3859 vm_size_t size;
3860
3861 size = s->getLength();
91447636 3862 kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
1c79356b
A
3863 if ( kr == kIOReturnSuccess ) {
3864 bcopy(s->text(), (void *)data, size);
91447636
A
3865 kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
3866 (vm_map_size_t)size, true, &copy);
1c79356b
A
3867 *outData = (char *)copy;
3868 *outDataCount = size;
3869 }
3870 }
3871
3872 s->release();
3873
3874 return kr;
3875}
3876
3877/* Routine io_catalog_get_gen_count */
3878kern_return_t is_io_catalog_get_gen_count(
3879 mach_port_t master_port,
2d21ac55 3880 uint32_t *genCount)
1c79356b
A
3881{
3882 if( master_port != master_device_port)
3883 return kIOReturnNotPrivileged;
3884
3885 //printf("io_catalog_get_gen_count called.\n");
3886
3887 if ( !genCount )
3888 return kIOReturnBadArgument;
3889
3890 *genCount = gIOCatalogue->getGenerationCount();
3891
3892 return kIOReturnSuccess;
3893}
3894
3895/* Routine io_catalog_module_loaded */
3896kern_return_t is_io_catalog_module_loaded(
3897 mach_port_t master_port,
3898 io_name_t name)
3899{
3900 if( master_port != master_device_port)
3901 return kIOReturnNotPrivileged;
3902
3903 //printf("io_catalog_module_loaded called. name %s\n", name);
3904
3905 if ( !name )
3906 return kIOReturnBadArgument;
3907
3908 gIOCatalogue->moduleHasLoaded(name);
3909
3910 return kIOReturnSuccess;
3911}
3912
3913kern_return_t is_io_catalog_reset(
3914 mach_port_t master_port,
2d21ac55 3915 uint32_t flag)
1c79356b
A
3916{
3917 if( master_port != master_device_port)
3918 return kIOReturnNotPrivileged;
3919
3920 switch ( flag ) {
3921 case kIOCatalogResetDefault:
3922 gIOCatalogue->reset();
3923 break;
3924
3925 default:
3926 return kIOReturnBadArgument;
3927 }
3928
3929 return kIOReturnSuccess;
3930}
3931
91447636 3932kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
1c79356b 3933{
0b4e3aa0
A
3934 kern_return_t result = kIOReturnBadArgument;
3935 IOUserClient *userClient;
1c79356b 3936
0b4e3aa0 3937 if ((userClient = OSDynamicCast(IOUserClient,
91447636 3938 iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
0b4e3aa0
A
3939 IOExternalTrap *trap;
3940 IOService *target = NULL;
1c79356b 3941
91447636 3942 trap = userClient->getTargetAndTrapForIndex(&target, args->index);
1c79356b 3943
0b4e3aa0
A
3944 if (trap && target) {
3945 IOTrap func;
1c79356b 3946
0b4e3aa0 3947 func = trap->func;
1c79356b 3948
0b4e3aa0 3949 if (func) {
91447636 3950 result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
0b4e3aa0
A
3951 }
3952 }
1c79356b 3953
0b4e3aa0
A
3954 userClient->release();
3955 }
1c79356b 3956
0b4e3aa0 3957 return result;
1c79356b
A
3958}
3959
2d21ac55
A
3960IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
3961 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
3962{
3963 IOReturn err;
3964 IOService * object;
3965
3966 if (dispatch)
3967 {
3968 uint32_t count;
3969 count = dispatch->checkScalarInputCount;
3970 if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount))
3971 {
3972 return (kIOReturnBadArgument);
3973 }
3974
3975 count = dispatch->checkStructureInputSize;
3976 if ((kIOUCVariableStructureSize != count)
3977 && (count != ((args->structureInputDescriptor)
3978 ? args->structureInputDescriptor->getLength() : args->structureInputSize)))
3979 {
3980 return (kIOReturnBadArgument);
3981 }
3982
3983 count = dispatch->checkScalarOutputCount;
3984 if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount))
3985 {
3986 return (kIOReturnBadArgument);
3987 }
3988
3989 count = dispatch->checkStructureOutputSize;
3990 if ((kIOUCVariableStructureSize != count)
3991 && (count != ((args->structureOutputDescriptor)
3992 ? args->structureOutputDescriptor->getLength() : args->structureOutputSize)))
3993 {
3994 return (kIOReturnBadArgument);
3995 }
3996
3997 if (dispatch->function)
3998 err = (*dispatch->function)(target, reference, args);
3999 else
4000 err = kIOReturnNoCompletion; /* implementator can dispatch */
4001
4002 return (err);
4003 }
4004
4005 // pre-Leopard API's don't do ool structs
4006 if (args->structureInputDescriptor || args->structureOutputDescriptor)
4007 {
4008 err = kIOReturnIPCError;
4009 return (err);
4010 }
4011
4012 if (args->asyncWakePort)
4013 {
4014 IOExternalAsyncMethod * method;
4015
4016 if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) )
4017 return (kIOReturnUnsupported);
4018
4019 switch (method->flags & kIOUCTypeMask)
4020 {
4021 case kIOUCScalarIStructI:
4022 err = shim_io_async_method_scalarI_structureI( method, object,
4023 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4024 args->scalarInput, args->scalarInputCount,
4025 (char *)args->structureInput, args->structureInputSize );
4026 break;
4027
4028 case kIOUCScalarIScalarO:
4029 err = shim_io_async_method_scalarI_scalarO( method, object,
4030 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4031 args->scalarInput, args->scalarInputCount,
4032 args->scalarOutput, &args->scalarOutputCount );
4033 break;
4034
4035 case kIOUCScalarIStructO:
4036 err = shim_io_async_method_scalarI_structureO( method, object,
4037 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4038 args->scalarInput, args->scalarInputCount,
4039 (char *) args->structureOutput, &args->structureOutputSize );
4040 break;
4041
4042
4043 case kIOUCStructIStructO:
4044 err = shim_io_async_method_structureI_structureO( method, object,
4045 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4046 (char *)args->structureInput, args->structureInputSize,
4047 (char *) args->structureOutput, &args->structureOutputSize );
4048 break;
4049
4050 default:
4051 err = kIOReturnBadArgument;
4052 break;
4053 }
4054 }
4055 else
4056 {
4057 IOExternalMethod * method;
4058
4059 if( !(method = getTargetAndMethodForIndex(&object, selector)) )
4060 return (kIOReturnUnsupported);
4061
4062 switch (method->flags & kIOUCTypeMask)
4063 {
4064 case kIOUCScalarIStructI:
4065 err = shim_io_connect_method_scalarI_structureI( method, object,
4066 args->scalarInput, args->scalarInputCount,
4067 (char *)args->structureInput, args->structureInputSize );
4068 break;
4069
4070 case kIOUCScalarIScalarO:
4071 err = shim_io_connect_method_scalarI_scalarO( method, object,
4072 args->scalarInput, args->scalarInputCount,
4073 args->scalarOutput, &args->scalarOutputCount );
4074 break;
4075
4076 case kIOUCScalarIStructO:
4077 err = shim_io_connect_method_scalarI_structureO( method, object,
4078 args->scalarInput, args->scalarInputCount,
4079 (char *) args->structureOutput, &args->structureOutputSize );
4080 break;
4081
4082
4083 case kIOUCStructIStructO:
4084 err = shim_io_connect_method_structureI_structureO( method, object,
4085 (char *)args->structureInput, args->structureInputSize,
4086 (char *) args->structureOutput, &args->structureOutputSize );
4087 break;
4088
4089 default:
4090 err = kIOReturnBadArgument;
4091 break;
4092 }
4093 }
4094 return (err);
4095}
4096
4097
1c79356b
A
4098}; /* extern "C" */
4099
2d21ac55 4100OSMetaClassDefineReservedUsed(IOUserClient, 0);
1c79356b
A
4101OSMetaClassDefineReservedUnused(IOUserClient, 1);
4102OSMetaClassDefineReservedUnused(IOUserClient, 2);
4103OSMetaClassDefineReservedUnused(IOUserClient, 3);
4104OSMetaClassDefineReservedUnused(IOUserClient, 4);
4105OSMetaClassDefineReservedUnused(IOUserClient, 5);
4106OSMetaClassDefineReservedUnused(IOUserClient, 6);
4107OSMetaClassDefineReservedUnused(IOUserClient, 7);
4108OSMetaClassDefineReservedUnused(IOUserClient, 8);
4109OSMetaClassDefineReservedUnused(IOUserClient, 9);
4110OSMetaClassDefineReservedUnused(IOUserClient, 10);
4111OSMetaClassDefineReservedUnused(IOUserClient, 11);
4112OSMetaClassDefineReservedUnused(IOUserClient, 12);
4113OSMetaClassDefineReservedUnused(IOUserClient, 13);
4114OSMetaClassDefineReservedUnused(IOUserClient, 14);
4115OSMetaClassDefineReservedUnused(IOUserClient, 15);
4116