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