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