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