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