1/*
2 * Copyright (c) 1998-2012 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef IOCONNECT_MAPMEMORY_10_6
25#define IOCONNECT_MAPMEMORY_10_6	1
26#endif
27
28#include <IOKit/IOTypes.h>
29#include <device/device_types.h>
30
31#include <mach/mach.h>
32#include <mach/mach_port.h>
33
34#if TARGET_IPHONE_SIMULATOR
35#include <servers/bootstrap.h>
36#endif
37
38#include <stdlib.h>
39#include <stdarg.h>
40#include <sys/file.h>
41#include <sys/stat.h>
42#include <sys/mman.h>
43#include <unistd.h>
44#include <asl.h>
45#include <dispatch/dispatch.h>
46#include <dispatch/private.h>
47
48#include <CoreFoundation/CoreFoundation.h>
49#include <CoreFoundation/CFMachPort.h>
50
51
52#include <IOKit/IOBSD.h>
53#include <IOKit/IOKitLib.h>
54#include <IOKit/IOKitServer.h>
55
56#include <IOKit/IOCFSerialize.h>
57#include <IOKit/IOCFUnserialize.h>
58
59#include <IOKit/IOKitLibPrivate.h>
60
61#if __LP64__
62static const int kIsLP64 = 1;
63typedef struct OSNotificationHeader64 NotificationHeader;
64
65// XXX gvdl: Need to conditionalise this for LP64
66#define mig_external __private_extern__
67#include <iokitmig64.h>
68#undef mig_external
69
70#else
71
72// To stage the IOKitUser map the 64 bit aware APIs locally
73#   if EMULATE_IOCONNECT
74#	define EMULATE_IOCONNECT_64		1
75#	define EMULATE_IOCONNECT_ASYNC_64	1
76#   endif
77
78#   if EMULATE_IOCONNECT_64
79#	define io_connect_method	em_connect_method
80#   endif
81
82#   if EMULATE_IOCONNECT_ASYNC_64
83#	define io_connect_async_method	em_connect_async_method
84#   endif
85
86typedef struct OSNotificationHeader NotificationHeader;
87static const int kIsLP64 = 0;
88#include <iokitmig32.h>
89
90#endif
91
92
93/*
94 * Ports
95 */
96
97extern 	mach_port_t 	mach_task_self();
98const 	mach_port_t 	kIOMasterPortDefault = MACH_PORT_NULL;
99
100static mach_port_t
101__IOGetDefaultMasterPort()
102{
103    mach_port_t masterPort;
104
105    kern_return_t result = IOMasterPort(MACH_PORT_NULL, &masterPort);
106    if( KERN_SUCCESS != result)
107	masterPort = MACH_PORT_NULL;
108
109    return( masterPort );
110}
111
112kern_return_t
113#if TARGET_IPHONE_SIMULATOR
114IOMasterPort( mach_port_t bootstrapPort, mach_port_t * masterPort )
115#else
116IOMasterPort( mach_port_t bootstrapPort __unused, mach_port_t * masterPort )
117#endif
118{
119    kern_return_t result = KERN_SUCCESS;
120    mach_port_t host_port = 0;
121
122#if TARGET_IPHONE_SIMULATOR
123    /* Defaulting to bypass until <rdar://problem/13141176> is addressed */
124    static boolean_t use_iokitsimd = 0;
125    static dispatch_once_t once;
126
127     dispatch_once(&once, ^{
128        const char *value = getenv("IOS_SIMULATOR_IOKITSIMD");
129
130        if (value) {
131            use_iokitsimd = (*value == '1');
132        }
133
134        if (!use_iokitsimd)
135            asl_log(NULL, NULL, ASL_LEVEL_NOTICE,
136                    "IOKit.framework:IOMasterPort bypassing iokitsimd");
137    });
138
139    if (use_iokitsimd) {
140        if (bootstrapPort == MACH_PORT_NULL)
141            bootstrapPort = bootstrap_port;
142        return bootstrap_look_up(bootstrapPort, "com.apple.iokitsimd", masterPort);
143    }
144#endif
145
146    host_port = mach_host_self();
147    result = host_get_io_master(host_port, masterPort);
148
149   /* Dispose of the host port to prevent security breaches and port
150    * leaks. We don't care about the kern_return_t value of this
151    * call for now as there's nothing we can do if it fails.
152    */
153    if (host_port) mach_port_deallocate(mach_task_self(), host_port);
154    return result;
155}
156
157kern_return_t
158IOCreateReceivePort( uint32_t msgType, mach_port_t * recvPort )
159{
160    kern_return_t res;
161    switch (msgType) {
162        case kOSNotificationMessageID:
163        case kOSAsyncCompleteMessageID:
164            res = mach_port_allocate(mach_task_self(),
165                                     MACH_PORT_RIGHT_RECEIVE, recvPort);
166
167            break;
168
169        default:
170            res = kIOReturnBadArgument;
171    }
172    return res;
173}
174
175/*
176 * IOObject
177 */
178
179kern_return_t
180IOObjectRelease(
181	io_object_t	object )
182{
183    return( mach_port_deallocate( mach_task_self(), object ));
184}
185
186kern_return_t
187IOObjectRetain(
188	io_object_t	object )
189{
190    return( mach_port_mod_refs(mach_task_self(),
191                              object,
192                              MACH_PORT_RIGHT_SEND,
193                              1 ));
194}
195
196kern_return_t
197IOObjectGetClass(
198	io_object_t	object,
199	io_name_t       className )
200{
201    return( io_object_get_class( object, className ));
202}
203
204
205CFStringRef
206IOObjectCopyClass(io_object_t object)
207{
208    io_name_t my_name;
209    CFStringRef my_str = NULL;
210
211    // if there's no argument, no point going on.  Return NULL.
212    if (!object)
213	return my_str;
214
215    io_object_get_class( object, my_name );
216    my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8);
217
218    return my_str;
219}
220
221CFStringRef
222IOObjectCopySuperclassForClass(CFStringRef classname)
223{
224    io_name_t my_name, orig_name;
225    CFStringRef my_str = NULL;
226    char * my_cstr;
227    kern_return_t kr;
228
229    // if there's no argument, no point going on.  Return NULL.
230    if (classname == NULL) {
231	return my_str;
232    }
233
234    my_cstr = malloc(sizeof(char) * 128);
235    CFStringGetCString (classname, my_cstr, 128, kCFStringEncodingUTF8);
236
237    strncpy(orig_name, my_cstr, sizeof(io_name_t));
238
239    mach_port_t masterPort = __IOGetDefaultMasterPort();
240
241    kr = io_object_get_superclass(masterPort, orig_name, my_name);
242
243    if (masterPort != MACH_PORT_NULL)
244	mach_port_deallocate(mach_task_self(), masterPort);
245
246    if (kr == kIOReturnSuccess) {
247	my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8);
248    }
249    free(my_cstr);
250
251    return my_str;
252}
253
254CFStringRef
255IOObjectCopyBundleIdentifierForClass(CFStringRef classname)
256{
257    io_name_t my_name, orig_name;
258    CFStringRef my_str = NULL;
259    char * my_cstr;
260    kern_return_t kr;
261
262    // if there's no argument, no point going on.  Return NULL.
263    if (classname == NULL) {
264	return my_str;
265    }
266
267    my_cstr = malloc(sizeof(char) * 128);
268    CFStringGetCString (classname, my_cstr, 128, kCFStringEncodingUTF8);
269
270    strncpy(orig_name, my_cstr, sizeof(io_name_t));
271
272    mach_port_t masterPort = __IOGetDefaultMasterPort();
273
274    kr = io_object_get_bundle_identifier(masterPort, orig_name, my_name);
275
276    if (masterPort != MACH_PORT_NULL)
277	mach_port_deallocate(mach_task_self(), masterPort);
278
279    if (kr == kIOReturnSuccess) {
280	my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8);
281    }
282    free(my_cstr);
283
284    return my_str;
285}
286
287boolean_t
288IOObjectConformsTo(
289	io_object_t	object,
290	const io_name_t	className )
291{
292    boolean_t	conforms;
293
294    if( kIOReturnSuccess != io_object_conforms_to(
295		object, (char *) className, &conforms ))
296	conforms = 0;
297
298    return( conforms );
299}
300
301boolean_t
302IOObjectIsEqualTo(
303	io_object_t	object,
304	io_object_t	anObject )
305{
306    return( object == anObject );
307}
308
309uint32_t
310IOObjectGetKernelRetainCount(
311	io_object_t	object )
312{
313    uint32_t	count;
314
315    if( kIOReturnSuccess != io_object_get_retain_count( object, &count))
316	count = 0;
317
318    return( count );
319}
320
321uint32_t
322IOObjectGetRetainCount(
323	io_object_t	object )
324{
325    return( IOObjectGetKernelRetainCount(object) );
326}
327
328uint32_t
329IOObjectGetUserRetainCount(
330	io_object_t	object )
331{
332    mach_port_urefs_t urefs;
333
334    if( kIOReturnSuccess != mach_port_get_refs( mach_task_self(), object, MACH_PORT_RIGHT_SEND, &urefs))
335	urefs = 0;
336
337    return( urefs );
338}
339
340/*
341 * IOIterator
342 */
343
344io_object_t
345IOIteratorNext(
346	io_iterator_t	iterator )
347{
348    io_object_t	next;
349
350    if( kIOReturnSuccess != io_iterator_next( iterator, &next))
351	next = 0;
352
353    return( next );
354}
355
356void
357IOIteratorReset(
358	io_iterator_t	iterator )
359{
360    io_iterator_reset( iterator );
361}
362
363boolean_t
364IOIteratorIsValid(
365	io_iterator_t	iterator )
366{
367    boolean_t	valid;
368
369    if( kIOReturnSuccess != io_iterator_is_valid( iterator, &valid ))
370	valid = FALSE;
371
372    return( valid );
373}
374
375/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
376
377/*
378 * IOService
379 */
380
381io_service_t
382IOServiceGetMatchingService(
383	mach_port_t	_masterPort,
384	CFDictionaryRef	matching )
385{
386    kern_return_t	kr;
387    CFDataRef		data;
388    CFIndex		dataLen;
389    mach_port_t		masterPort;
390    io_service_t        service = MACH_PORT_NULL;
391
392    if( !matching)
393	return( MACH_PORT_NULL);
394
395    data = IOCFSerialize( matching, kNilOptions );
396    CFRelease( matching );
397    if( !data)
398	return( MACH_PORT_NULL );
399
400    dataLen = CFDataGetLength(data);
401
402    if (MACH_PORT_NULL == _masterPort)
403	masterPort = __IOGetDefaultMasterPort();
404    else
405	masterPort = _masterPort;
406
407    if ((size_t) dataLen < sizeof(io_string_t))
408	kr = io_service_get_matching_service( masterPort,
409		    (char *) CFDataGetBytePtr(data), &service );
410    else {
411	kern_return_t result;
412
413	kr = io_service_get_matching_service_ool( masterPort,
414		    (char *) CFDataGetBytePtr(data), dataLen, &result, &service );
415	if (KERN_SUCCESS == kr)
416	    kr = result;
417    }
418
419    CFRelease( data );
420    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
421	mach_port_deallocate(mach_task_self(), masterPort);
422
423   if (KERN_SUCCESS != kr)
424	service = MACH_PORT_NULL;
425
426    return( service );
427}
428
429kern_return_t
430IOServiceGetMatchingServices(
431        mach_port_t	_masterPort,
432	CFDictionaryRef	matching,
433	io_iterator_t * existing )
434{
435    kern_return_t	kr;
436    CFDataRef		data;
437    CFIndex		dataLen;
438    mach_port_t		masterPort;
439
440    if( !matching)
441	return( kIOReturnBadArgument);
442
443    data = IOCFSerialize( matching, kNilOptions );
444    CFRelease( matching );
445    if( !data)
446	return( kIOReturnUnsupported );
447
448    dataLen = CFDataGetLength(data);
449
450    if (MACH_PORT_NULL == _masterPort)
451	masterPort = __IOGetDefaultMasterPort();
452    else
453	masterPort = _masterPort;
454
455    if ((size_t) dataLen < sizeof(io_string_t))
456	kr = io_service_get_matching_services( masterPort,
457		    (char *) CFDataGetBytePtr(data), existing );
458    else {
459	kern_return_t result;
460
461	kr = io_service_get_matching_services_ool( masterPort,
462		    (char *) CFDataGetBytePtr(data), dataLen, &result, existing );
463	if (KERN_SUCCESS == kr)
464	    kr = result;
465    }
466
467    CFRelease( data );
468    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
469	mach_port_deallocate(mach_task_self(), masterPort);
470
471    return( kr );
472}
473
474kern_return_t
475IOServiceMatchPropertyTable( io_service_t service, CFDictionaryRef matching,
476                  boolean_t * matches )
477{
478    kern_return_t	kr;
479    CFDataRef		data;
480    CFIndex		dataLen;
481
482    if( !matching)
483	return( kIOReturnBadArgument);
484
485    data = IOCFSerialize( matching, kNilOptions );
486    if( !data)
487	return( kIOReturnUnsupported );
488
489
490    dataLen = CFDataGetLength(data);
491
492    if ((size_t) dataLen < sizeof(io_string_t))
493	kr = io_service_match_property_table( service,
494		    (char *) CFDataGetBytePtr(data), matches );
495    else {
496	kern_return_t result;
497
498	kr = io_service_match_property_table_ool( service,
499		    (char *) CFDataGetBytePtr(data), dataLen, &result, matches );
500	if (KERN_SUCCESS == kr)
501	    kr = result;
502    }
503
504    CFRelease( data );
505
506    return( kr );
507}
508
509kern_return_t
510IOServiceAddNotification(
511        mach_port_t	 _masterPort,
512	const io_name_t	 notificationType,
513	CFDictionaryRef	 matching,
514	mach_port_t	 wakePort,
515	uintptr_t	 reference,
516	io_iterator_t 	*notification )
517{
518    kern_return_t	kr;
519    CFDataRef		data;
520    CFIndex		dataLen;
521    mach_port_t		masterPort;
522
523    if( !matching)
524	return( kIOReturnBadArgument);
525
526    data = IOCFSerialize( matching, kNilOptions );
527    CFRelease( matching );
528    if( !data)
529	return( kIOReturnUnsupported );
530
531    dataLen = CFDataGetLength(data);
532
533    if (MACH_PORT_NULL == _masterPort)
534	masterPort = __IOGetDefaultMasterPort();
535    else
536	masterPort = _masterPort;
537
538    if ((size_t) dataLen < sizeof(io_string_t))
539	kr = io_service_add_notification( masterPort, (char *) notificationType,
540		    (char *) CFDataGetBytePtr(data),
541		    wakePort, (io_user_reference_t *) &reference, 1,
542		    notification );
543    else {
544	kern_return_t result;
545
546	kr = io_service_add_notification_ool( masterPort, (char *) notificationType,
547		    (char *) CFDataGetBytePtr(data), dataLen,
548		    wakePort, (io_user_reference_t *) &reference, 1,
549		    &result, notification );
550	if (KERN_SUCCESS == kr)
551	    kr = result;
552    }
553
554    CFRelease( data );
555    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
556	mach_port_deallocate(mach_task_self(), masterPort);
557
558    return( kr );
559}
560
561kern_return_t
562IOServiceAddMatchingNotification(
563	IONotificationPortRef	notifyPort,
564	const io_name_t		notificationType,
565	CFDictionaryRef		matching,
566        IOServiceMatchingCallback callback,
567        void *			refcon,
568	io_iterator_t * 	notification )
569{
570    kern_return_t	kr;
571    CFDataRef		data;
572    CFIndex		dataLen;
573    io_user_reference_t	asyncRef[kIOMatchingCalloutCount];
574
575    if( !matching)
576	return( kIOReturnBadArgument);
577
578    data = IOCFSerialize( matching, kNilOptions );
579    CFRelease( matching );
580    if( !data)
581	return( kIOReturnUnsupported );
582
583    asyncRef[kIOMatchingCalloutFuncIndex]   = (io_user_reference_t) callback;
584    asyncRef[kIOMatchingCalloutRefconIndex] = (io_user_reference_t) refcon;
585
586    dataLen = CFDataGetLength(data);
587
588    if ((size_t) dataLen < sizeof(io_string_t))
589	kr = io_service_add_notification( notifyPort->masterPort,
590		    (char *) notificationType,
591		    (char *) CFDataGetBytePtr(data),
592		    notifyPort->wakePort,
593		    asyncRef, kIOMatchingCalloutCount, notification );
594    else {
595	kern_return_t result;
596
597	kr = io_service_add_notification_ool( notifyPort->masterPort,
598		    (char *) notificationType,
599		    (char *) CFDataGetBytePtr(data), dataLen,
600		    notifyPort->wakePort,
601		    asyncRef, kIOMatchingCalloutCount, &result, notification );
602	if (KERN_SUCCESS == kr)
603	    kr = result;
604    }
605
606    CFRelease( data );
607
608    return( kr );
609}
610
611kern_return_t
612IOServiceAddInterestNotification(
613	IONotificationPortRef	notifyPort,
614        io_service_t		service,
615	const io_name_t 	interestType,
616        IOServiceInterestCallback callback,
617        void *			refcon,
618        io_object_t *		notification )
619{
620    io_user_reference_t	asyncRef[kIOInterestCalloutCount];
621    kern_return_t	kr;
622
623    asyncRef[kIOInterestCalloutFuncIndex]    = (io_user_reference_t) callback;
624    asyncRef[kIOInterestCalloutRefconIndex]  = (io_user_reference_t) refcon;
625    asyncRef[kIOInterestCalloutServiceIndex] = (io_user_reference_t) service;
626
627    kr = io_service_add_interest_notification( service, (char *) interestType,
628                            notifyPort->wakePort,
629                            asyncRef, kIOInterestCalloutCount,
630                            notification );
631
632    return( kr );
633}
634
635IONotificationPortRef
636IONotificationPortCreate(
637	mach_port_t	masterPort )
638{
639    kern_return_t 	        kr;
640    IONotificationPort     *notify;
641
642    if (MACH_PORT_NULL == masterPort) {
643        masterPort = __IOGetDefaultMasterPort();
644    } else {
645        IOObjectRetain(masterPort);
646    }
647
648    notify = calloc( 1, sizeof( IONotificationPort));
649    if (!notify) {
650        return( 0 );
651    }
652    notify->masterPort = masterPort;
653
654    kr = IOCreateReceivePort(kOSNotificationMessageID, &notify->wakePort);
655    if( kr != kIOReturnSuccess) {
656        free( notify );
657        return( 0 );
658    }
659
660    return notify;
661}
662
663void
664IONotificationPortDestroy(
665	IONotificationPortRef	notify )
666{
667
668    if (notify->cfmachPort) {
669        CFMachPortInvalidate(notify->cfmachPort);
670        CFRelease(notify->cfmachPort);
671    }
672
673    if( notify->source) {
674        CFRelease(notify->source);
675    }
676
677    if (notify->dispatchSource) {
678        dispatch_release(notify->dispatchSource);
679    }
680
681    mach_port_mod_refs(mach_task_self(), notify->wakePort,
682                        MACH_PORT_RIGHT_RECEIVE, -1);
683
684    mach_port_deallocate(mach_task_self(), notify->masterPort);
685
686    free( notify );
687}
688
689CFRunLoopSourceRef
690IONotificationPortGetRunLoopSource(
691	IONotificationPortRef	notify )
692{
693    CFMachPortContext 	    context;
694    Boolean		            cfReusedPort = false;
695
696    if (notify->source)
697        return (notify->source);
698
699    context.version = 1;
700    context.info = (void *) notify;
701    context.retain = NULL;
702    context.release = NULL;
703    context.copyDescription = NULL;
704
705    notify->cfmachPort = CFMachPortCreateWithPort(NULL, notify->wakePort,
706        IODispatchCalloutFromCFMessage, &context, &cfReusedPort);
707    if (!notify->cfmachPort)
708        return NULL;
709
710    if (cfReusedPort)
711    {
712        // We got a CFMachPortRef that CF re-used from its pool.
713        // This is probably a race condition, and this belongs
714        // to a recently dead port.
715        // We expect a new CFMachPortRef - we treat it as an error.
716
717        CFStringRef     description = NULL;
718        char            str[255];
719        if (notify->cfmachPort) {
720            description = CFCopyDescription(notify->cfmachPort);
721            if (description) {
722                CFStringGetCString(description, str, sizeof(str), kCFStringEncodingUTF8);
723                CFRelease(description);
724            }
725        }
726
727        asl_log(NULL, NULL, ASL_LEVEL_ERR,
728                "IOKit.framework:IONotificationPortGetRunLoopSource bad CFMachPort, %s\n",
729                description ? str : "No Description");
730
731        CFRelease(notify->cfmachPort);
732        notify->cfmachPort = NULL;
733        goto exit;
734    }
735
736    notify->source = CFMachPortCreateRunLoopSource(NULL, notify->cfmachPort, 0);
737
738exit:
739    return (notify->source);
740}
741
742mach_port_t
743IONotificationPortGetMachPort(
744	IONotificationPortRef	notify )
745{
746    return( notify->wakePort );
747}
748
749boolean_t _IODispatchCalloutWithDispatch(mach_msg_header_t *msg, mach_msg_header_t *reply)
750{
751    mig_reply_setup(msg, reply);
752    ((mig_reply_error_t*)reply)->RetCode = MIG_NO_REPLY;
753
754    IODispatchCalloutFromCFMessage(NULL, msg, msg->msgh_size, dispatch_mach_msg_get_context(msg));
755    return TRUE;
756}
757
758#define MAX_MSG_SIZE (8ul * 1024ul - MAX_TRAILER_SIZE)
759
760void
761IONotificationPortSetDispatchQueue(IONotificationPortRef notify, dispatch_queue_t queue)
762{
763    if (!queue) return;
764
765    if (notify->dispatchSource)
766    {
767        dispatch_release(notify->dispatchSource);
768        notify->dispatchSource = NULL;
769    }
770
771    notify->dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, notify->wakePort, 0, queue);
772    dispatch_source_set_event_handler(notify->dispatchSource, ^{
773        dispatch_mig_server(notify->dispatchSource, MAX_MSG_SIZE, _IODispatchCalloutWithDispatch);
774    });
775
776   /* Note: normally, dispatch sources for mach ports should destroy the underlying
777    * mach port in their cancellation handler.  We take care to destroy the port
778    * after we destroy the source in IONotificationPortDestroy(), which gives us the
779    * flexibility of changing the queue used for the dispatch source.
780    */
781
782    dispatch_resume(notify->dispatchSource);
783}
784
785/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
786
787/*
788 * Matching creation helpers
789 */
790
791static CFMutableDictionaryRef
792MakeOneStringProp(
793	CFStringRef	key,
794	const char *	name )
795{
796    CFMutableDictionaryRef	dict;
797    CFStringRef			string;
798
799    dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
800		&kCFTypeDictionaryKeyCallBacks,
801		&kCFTypeDictionaryValueCallBacks);
802
803    if( !dict)
804	return( dict);
805
806    string = CFStringCreateWithCString( kCFAllocatorDefault, name,
807					kCFStringEncodingMacRoman );
808
809    if( string) {
810        CFDictionarySetValue( dict, key, string );
811        CFRelease( string );
812    } else {
813	CFRelease( dict );
814	dict = 0;
815    }
816
817    return( dict );
818}
819
820static CFMutableDictionaryRef
821MakeOneNumProp(
822	CFStringRef	key,
823	uint64_t	value )
824{
825    CFMutableDictionaryRef	dict;
826    CFNumberRef			num;
827
828    dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
829		&kCFTypeDictionaryKeyCallBacks,
830		&kCFTypeDictionaryValueCallBacks);
831
832    if( !dict)
833	return( dict);
834
835    num = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt64Type, &value );
836    if( num) {
837        CFDictionarySetValue( dict, key, num );
838        CFRelease( num );
839    } else {
840	CFRelease( dict );
841	dict = 0;
842    }
843
844    return( dict );
845}
846
847
848CFMutableDictionaryRef
849IOServiceMatching(
850	const char *	name )
851{
852    return( MakeOneStringProp( CFSTR(kIOProviderClassKey), name ) );
853}
854
855CFMutableDictionaryRef
856IOServiceNameMatching(
857	const char *	name )
858{
859    return( MakeOneStringProp( CFSTR(kIONameMatchKey), name ));
860}
861
862CFMutableDictionaryRef
863IORegistryEntryIDMatching(
864	uint64_t	entryID )
865{
866    return( MakeOneNumProp( CFSTR(kIORegistryEntryIDKey), entryID ));
867}
868
869CFMutableDictionaryRef
870IOBSDNameMatching(
871    mach_port_t		masterPort	__unused,
872	uint32_t		options 	__unused,
873	const char *	name )
874{
875    if( !name)
876	return( 0 );
877
878    return( MakeOneStringProp( CFSTR(kIOBSDNameKey), name ));
879}
880
881CFMutableDictionaryRef
882IOOpenFirmwarePathMatching(
883	mach_port_t	masterPort __unused,
884	uint32_t	options 	__unused,
885	const char *	path )
886{
887    io_string_t	buf;
888    int		maxLen;
889    char *	comp;
890    int		len;
891
892    maxLen = sizeof( io_string_t);
893
894    do {
895
896	len = strlen( kIODeviceTreePlane ":" );
897	maxLen -= len;
898	if( maxLen <= 0)
899	    continue;
900
901	strlcpy( buf, kIODeviceTreePlane ":", len + 1 );
902	comp = buf + len;
903
904	len = strlen( path );
905	maxLen -= len;
906	if( maxLen <= 0)
907	    continue;
908	strlcpy( comp, path, len + 1 );
909
910	return( MakeOneStringProp( CFSTR(kIOPathMatchKey), buf ));
911
912    } while( false );
913
914    return( 0 );
915}
916
917/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
918
919kern_return_t
920OSGetNotificationFromMessage(
921	mach_msg_header_t	 *msg,
922	uint32_t		  index,
923        uint32_t		 *type,
924        uintptr_t		 *reference,
925	void			**content,
926        vm_size_t		 *size )
927{
928    // The kernel handles the downcast of the reference vector for 32bit tasks
929    NotificationHeader *	header;
930
931    if( msg->msgh_id != kOSNotificationMessageID)
932	return( kIOReturnBadMessageID );
933
934    if( msg->msgh_size < (sizeof( mach_msg_header_t)
935			+ sizeof( NotificationHeader)))
936	return( kIOReturnNoResources );
937
938    if( index)
939	return( kIOReturnNoResources );
940
941    header = (NotificationHeader *) (msg + 1);
942    if( type)
943        *type = header->type;
944    if( reference)
945        *reference = (uintptr_t) header->reference[0];
946    if( size)
947        *size = header->size;
948    if( content) {
949	if( header->size)
950            *content = &header->content[0];
951        else
952            *content = 0;
953    }
954
955    return( kIOReturnSuccess );
956}
957
958/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
959
960void
961IODispatchCalloutFromMessage(void *cfPort, mach_msg_header_t *msg, void *info)
962{
963    return( IODispatchCalloutFromCFMessage( cfPort, msg, -1, info ));
964}
965
966void
967IODispatchCalloutFromCFMessage(CFMachPortRef port __unused,
968			void *_msg, CFIndex size __unused, void *info __unused)
969{
970    struct ComplexMsg {
971        mach_msg_header_t		msgHdr;
972	mach_msg_body_t			msgBody;
973	mach_msg_port_descriptor_t	ports[1];
974    } *					complexMsg = NULL;
975    mach_msg_header_t *			msg = (mach_msg_header_t *)_msg;
976    NotificationHeader *		header;
977    io_iterator_t			notifier = MACH_PORT_NULL;
978    io_service_t			service = MACH_PORT_NULL;
979    uint32_t				leftOver;
980    boolean_t				deliver = TRUE;
981
982    if( msg->msgh_id != kOSNotificationMessageID)
983	return;
984
985    if( MACH_MSGH_BITS_COMPLEX & msg->msgh_bits) {
986
987	complexMsg = (struct ComplexMsg *)_msg;
988
989	if( complexMsg->msgBody.msgh_descriptor_count)
990	    service = complexMsg->ports[0].name;
991	header = (NotificationHeader *) &complexMsg->ports[complexMsg->msgBody.msgh_descriptor_count];
992
993    } else
994	header = (NotificationHeader *) (msg + 1);
995
996    leftOver = msg->msgh_size - (((vm_address_t) (header + 1)) - ((vm_address_t) msg));
997
998    // remote port is the notification (an iterator_t) that fired
999    notifier = msg->msgh_remote_port;
1000
1001    if( MACH_PORT_NULL != notifier) {
1002	kern_return_t kr;
1003	mach_port_urefs_t urefs;
1004
1005	kr = mach_port_get_refs( mach_task_self(), msg->msgh_remote_port, MACH_PORT_RIGHT_SEND, &urefs);
1006	if( (KERN_SUCCESS != kr) || (urefs < 2)) {
1007	    // one ref carried by the message - < 2 means owner has released the notifier
1008	    deliver = false;
1009	}
1010    }
1011
1012    if(deliver)
1013    {
1014      switch( header->type )
1015      {
1016	case kIOAsyncCompletionNotificationType:
1017	{
1018	    IOAsyncCompletionContent *asyncHdr;
1019
1020	    asyncHdr = (IOAsyncCompletionContent *)(header + 1);
1021	    leftOver = (leftOver - sizeof(*asyncHdr)) / sizeof(void *);
1022	    void *func   = (void *) header->reference[kIOAsyncCalloutFuncIndex];
1023	    void *refCon = (void *) header->reference[kIOAsyncCalloutRefconIndex];
1024	    switch (leftOver) {
1025	    case 0:
1026		((IOAsyncCallback0) func)(refCon, asyncHdr->result);
1027		break;
1028	    case 1:
1029		((IOAsyncCallback1) func)(refCon, asyncHdr->result,
1030		    asyncHdr->args[0]);
1031		break;
1032	    case 2:
1033		((IOAsyncCallback2) func)(refCon, asyncHdr->result,
1034		    asyncHdr->args[0], asyncHdr->args[1]);
1035		break;
1036	    default:
1037		((IOAsyncCallback) func)(refCon, asyncHdr->result,
1038		    asyncHdr->args, leftOver);
1039		break;
1040	    }
1041	    break;
1042	}
1043	case kIOServiceMessageNotificationType:
1044	{
1045	    IOServiceInterestContent * interestHdr;
1046	    void * arg;
1047
1048	    interestHdr = (IOServiceInterestContent *)(header + 1);
1049	    leftOver = (leftOver - sizeof(*interestHdr) + sizeof(interestHdr->messageArgument)) / sizeof(void *);
1050	    if (leftOver <= 1)
1051		arg = interestHdr->messageArgument[0];
1052	    else
1053		arg = &interestHdr->messageArgument[0];
1054
1055	    ((IOServiceInterestCallback)header->reference[kIOInterestCalloutFuncIndex])(
1056		(void *) header->reference[kIOInterestCalloutRefconIndex],
1057		service ? service :  (io_service_t) header->reference[kIOInterestCalloutServiceIndex],
1058		interestHdr->messageType, arg );
1059	    break;
1060	}
1061	case kIOServicePublishNotificationType:
1062	case kIOServiceMatchedNotificationType:
1063	case kIOServiceTerminatedNotificationType:
1064
1065	    ((IOServiceMatchingCallback)header->reference[kIOMatchingCalloutFuncIndex])(
1066		(void *) header->reference[kIOMatchingCalloutRefconIndex],
1067		notifier);
1068	    break;
1069      }
1070    }
1071
1072    if( MACH_PORT_NULL != notifier)
1073	mach_port_deallocate( mach_task_self(), notifier );
1074    if( complexMsg)
1075    {
1076	uint32_t i;
1077	for( i = 0; i < complexMsg->msgBody.msgh_descriptor_count; i++)
1078	    mach_port_deallocate( mach_task_self(), complexMsg->ports[i].name );
1079    }
1080}
1081
1082/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1083
1084kern_return_t
1085IOServiceGetBusyStateAndTime(
1086	io_service_t    service,
1087	uint64_t *	state,
1088	uint32_t *	busy_state,
1089	uint64_t *	accumulated_busy_time)
1090{
1091    kern_return_t	kr;
1092
1093    kr = io_service_get_state( service, state, busy_state, accumulated_busy_time );
1094
1095    if (kr != KERN_SUCCESS)
1096    {
1097	*state = 0;
1098	*busy_state = 0;
1099	*accumulated_busy_time = 0;
1100    }
1101
1102    return( kr );
1103}
1104
1105kern_return_t
1106IOServiceGetBusyState(
1107	io_service_t    service,
1108	uint32_t *	busyState )
1109{
1110    uint64_t		state;
1111    uint64_t		accumulated_busy_time;
1112
1113    return (IOServiceGetBusyStateAndTime(service, &state, busyState, &accumulated_busy_time));
1114}
1115
1116kern_return_t
1117IOServiceGetState(
1118	io_service_t    service,
1119	uint64_t *	state )
1120{
1121    uint32_t		busy_state;
1122    uint64_t		accumulated_busy_time;
1123
1124    return (IOServiceGetBusyStateAndTime(service, state, &busy_state, &accumulated_busy_time));
1125}
1126
1127kern_return_t
1128IOKitGetBusyState(
1129        mach_port_t	_masterPort,
1130	uint32_t *	busyState )
1131{
1132    io_service_t 	root;
1133    kern_return_t	kr;
1134    mach_port_t		masterPort;
1135
1136    if (MACH_PORT_NULL == _masterPort)
1137	masterPort = __IOGetDefaultMasterPort();
1138    else
1139	masterPort = _masterPort;
1140
1141    kr = io_registry_entry_from_path( masterPort,
1142			kIOServicePlane ":/", &root );
1143
1144    if( kr == KERN_SUCCESS) {
1145	kr = IOServiceGetBusyState( root, busyState );
1146	IOObjectRelease( root );
1147    } else
1148	*busyState = 0;
1149
1150    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
1151	mach_port_deallocate(mach_task_self(), masterPort);
1152
1153    return( kr );
1154}
1155
1156kern_return_t
1157IOServiceWaitQuiet(
1158	io_service_t      service,
1159	mach_timespec_t * waitTime )
1160{
1161    kern_return_t	kr;
1162    mach_timespec_t	defaultWait = { 0, -1 };
1163
1164    if( 0 == waitTime)
1165        waitTime = &defaultWait;
1166
1167    kr = io_service_wait_quiet( service, *waitTime );
1168
1169    return( kr );
1170}
1171
1172
1173kern_return_t
1174IOKitWaitQuiet(
1175        mach_port_t	_masterPort,
1176	mach_timespec_t * waitTime )
1177{
1178    io_service_t 	root;
1179    kern_return_t	kr;
1180    mach_timespec_t	defaultWait = { 0, -1 };
1181    mach_port_t		masterPort;
1182
1183    if (MACH_PORT_NULL == _masterPort)
1184	masterPort = __IOGetDefaultMasterPort();
1185    else
1186	masterPort = _masterPort;
1187
1188    kr = io_registry_entry_from_path( masterPort,
1189			kIOServicePlane ":/", &root );
1190
1191    if( kr == KERN_SUCCESS) {
1192	if( 0 == waitTime)
1193	    waitTime = &defaultWait;
1194	kr = io_service_wait_quiet( root, *waitTime );
1195	IOObjectRelease( root );
1196    }
1197
1198    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
1199	mach_port_deallocate(mach_task_self(), masterPort);
1200
1201    return( kr );
1202}
1203
1204kern_return_t
1205IOServiceOpen(
1206	io_service_t    service,
1207	task_port_t	owningTask,
1208	uint32_t	type,
1209	io_connect_t  *	connect )
1210{
1211    kern_return_t	kr;
1212    kern_return_t	result;
1213
1214    kr = io_service_open_extended( service,
1215	owningTask, type, NDR_record, NULL, 0, &result, connect );
1216
1217    if (KERN_SUCCESS == kr)
1218        kr = result;
1219
1220    return (kr);
1221}
1222
1223kern_return_t
1224IOServiceClose(
1225	io_connect_t	connect )
1226{
1227    kern_return_t	kr;
1228
1229    kr = io_service_close( connect);
1230    IOObjectRelease( connect );
1231
1232    return( kr );
1233}
1234
1235kern_return_t
1236IOServiceRequestProbe(
1237	io_service_t    service,
1238	uint32_t	options )
1239{
1240    return( io_service_request_probe( service, options ));
1241}
1242
1243/*
1244 * IOService connection
1245 */
1246kern_return_t
1247IOConnectAddRef(
1248	io_connect_t	connect )
1249{
1250    return mach_port_mod_refs(mach_task_self(),
1251                              connect,
1252                              MACH_PORT_RIGHT_SEND,
1253                              1);
1254}
1255
1256kern_return_t
1257IOConnectRelease(
1258	io_connect_t	connect )
1259{
1260    // XXX gvdl: Check with Simon about last reference removal
1261    return mach_port_mod_refs(mach_task_self(),
1262                              connect,
1263                              MACH_PORT_RIGHT_SEND,
1264                              -1);
1265}
1266
1267kern_return_t
1268IOConnectGetService(
1269	io_connect_t	connect,
1270	io_service_t  *	service )
1271{
1272    return( io_connect_get_service( connect, service ));
1273}
1274
1275kern_return_t
1276IOConnectSetNotificationPort(
1277	io_connect_t	connect,
1278	uint32_t	type,
1279	mach_port_t	port,
1280	uintptr_t	reference )
1281{
1282    return( io_connect_set_notification_port( connect,
1283		type, port, reference));
1284}
1285
1286kern_return_t IOConnectMapMemory(
1287	 io_connect_t	connect,
1288	 uint32_t		memoryType,
1289	 task_port_t	intoTask,
1290	 vm_address_t	*atAddress,
1291	 vm_size_t		*ofSize,
1292	 IOOptionBits	options )
1293{
1294#if __LP64__
1295    return io_connect_map_memory_into_task
1296		(connect, memoryType, intoTask, (mach_vm_address_t *) atAddress, (mach_vm_size_t *) ofSize, options);
1297
1298#else
1299    return io_connect_map_memory
1300		(connect, memoryType, intoTask, atAddress, ofSize, options);
1301#endif
1302}
1303
1304kern_return_t IOConnectMapMemory64(
1305	 io_connect_t		connect,
1306	 uint32_t		memoryType,
1307	 task_port_t		intoTask,
1308	 mach_vm_address_t	*atAddress,
1309	 mach_vm_size_t		*ofSize,
1310	 IOOptionBits		options )
1311{
1312    return io_connect_map_memory_into_task
1313		(connect, memoryType, intoTask, atAddress, ofSize, options);
1314}
1315
1316kern_return_t
1317IOConnectUnmapMemory(
1318	io_connect_t		connect,
1319	uint32_t		memoryType,
1320	task_port_t		fromTask,
1321	vm_address_t		atAddress )
1322{
1323#if __LP64__
1324    return io_connect_unmap_memory_from_task
1325		(connect, memoryType, fromTask, atAddress);
1326#else
1327    return io_connect_unmap_memory
1328		(connect, memoryType, fromTask, atAddress);
1329#endif
1330}
1331
1332kern_return_t IOConnectUnmapMemory64(
1333	 io_connect_t		connect,
1334	 uint32_t		memoryType,
1335	 task_port_t		fromTask,
1336	 mach_vm_address_t	atAddress)
1337{
1338    return io_connect_unmap_memory_from_task
1339		(connect, memoryType, fromTask, atAddress);
1340}
1341
1342kern_return_t
1343IOConnectAddClient(
1344	io_connect_t	connect,
1345	io_connect_t	client )
1346{
1347    return( io_connect_add_client( connect, client));
1348}
1349
1350/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1351
1352#if USE_TRAP_TRANSPORT
1353
1354#define kUseTrapTransport 1
1355__private_extern__ char checkBegin = 0, checkEnd = 0;
1356static __inline__ void checkPtrRange(void *ptr, IOByteCount cnt)
1357{
1358    checkBegin = ((uint8_t *) ptr)[0];
1359    checkEnd   = ((uint8_t *) ptr)[cnt];
1360}
1361
1362#else
1363
1364#define kUseTrapTransport 0
1365
1366#endif /* USE_TRAP_TRANSPORT */
1367
1368#define reinterpret_cast_mach_vm_address_t(p) \
1369    ((mach_vm_address_t) (uintptr_t) p)
1370
1371kern_return_t
1372IOConnectCallMethod(
1373	mach_port_t	 connection,		// In
1374	uint32_t	 selector,		// In
1375	const uint64_t	*input,			// In
1376	uint32_t	 inputCnt,		// In
1377	const void	*inputStruct,		// In
1378	size_t		 inputStructCnt,	// In
1379	uint64_t	*output,		// Out
1380	uint32_t	*outputCnt,		// In/Out
1381	void		*outputStruct,		// Out
1382	size_t		*outputStructCntP)	// In/Out
1383{
1384    kern_return_t	        rtn;
1385
1386    void			*inb_input       = 0;
1387    mach_msg_type_number_t	 inb_input_size  = 0;
1388    void			*inb_output      = 0;
1389    mach_msg_type_number_t	 inb_output_size = 0;
1390
1391    mach_vm_address_t		 ool_input       = 0;
1392    mach_vm_size_t		 ool_input_size  = 0;
1393    mach_vm_address_t		 ool_output      = 0;
1394    mach_vm_size_t		 ool_output_size = 0;
1395    io_buf_ptr_t                 var_output      = NULL;
1396    mach_msg_type_number_t       var_output_size = 0;
1397
1398    if (inputStructCnt <= sizeof(io_struct_inband_t)) {
1399	inb_input      = (void *) inputStruct;
1400	inb_input_size = (mach_msg_type_number_t) inputStructCnt;
1401    }
1402    else {
1403	ool_input      = reinterpret_cast_mach_vm_address_t(inputStruct);
1404	ool_input_size = inputStructCnt;
1405    }
1406
1407    if (!outputCnt) {
1408	static uint32_t zero = 0;
1409	outputCnt = &zero;
1410    }
1411
1412    if (outputStructCntP) {
1413	size_t size = *outputStructCntP;
1414
1415	if (size == (size_t) kIOConnectMethodVarOutputSize) {
1416
1417	    rtn = io_connect_method_var_output(
1418	    			    connection,         selector,
1419				    (uint64_t *) input, inputCnt,
1420				    inb_input,          inb_input_size,
1421				    ool_input,          ool_input_size,
1422				    inb_output,         &inb_output_size,
1423				    output,             outputCnt,
1424				    &var_output,	&var_output_size);
1425
1426	    *(void **)outputStruct = var_output;
1427	    *outputStructCntP      = var_output_size;
1428
1429	    return (rtn);
1430
1431	}
1432	else if (size <= sizeof(io_struct_inband_t)) {
1433	    inb_output      = outputStruct;
1434	    inb_output_size = (mach_msg_type_number_t) size;
1435	}
1436	else {
1437	    ool_output      = reinterpret_cast_mach_vm_address_t(outputStruct);
1438	    ool_output_size = (mach_vm_size_t)    size;
1439	}
1440    }
1441
1442    rtn = io_connect_method(connection,         selector,
1443			    (uint64_t *) input, inputCnt,
1444			    inb_input,          inb_input_size,
1445			    ool_input,          ool_input_size,
1446			    inb_output,         &inb_output_size,
1447			    output,             outputCnt,
1448			    ool_output,         &ool_output_size);
1449
1450    if (outputStructCntP) {
1451	if (*outputStructCntP <= sizeof(io_struct_inband_t))
1452	    *outputStructCntP = (size_t) inb_output_size;
1453	else
1454	    *outputStructCntP = (size_t) ool_output_size;
1455    }
1456
1457    return rtn;
1458}
1459
1460kern_return_t
1461IOConnectCallAsyncMethod(
1462	mach_port_t	 connection,		// In
1463	uint32_t	 selector,		// In
1464	mach_port_t	 wakePort,		// In
1465	uint64_t	*reference,		// In
1466	uint32_t	 referenceCnt,		// In
1467	const uint64_t	*input,			// In
1468	uint32_t	 inputCnt,		// In
1469	const void	*inputStruct,		// In
1470	size_t		 inputStructCnt,	// In
1471	uint64_t	*output,		// Out
1472	uint32_t	*outputCnt,		// In/Out
1473	void		*outputStruct,		// Out
1474	size_t		*outputStructCntP)	// In/Out
1475{
1476    kern_return_t	        rtn;
1477
1478    void			*inb_input       = 0;
1479    mach_msg_type_number_t	 inb_input_size  = 0;
1480    void			*inb_output      = 0;
1481    mach_msg_type_number_t	 inb_output_size = 0;
1482
1483    mach_vm_address_t		 ool_input       = 0;
1484    mach_vm_size_t		 ool_input_size  = 0;
1485    mach_vm_address_t		 ool_output      = 0;
1486    mach_vm_size_t		 ool_output_size = 0;
1487
1488    if (inputStructCnt <= sizeof(io_struct_inband_t)) {
1489	inb_input      = (void *) inputStruct;
1490	inb_input_size = (mach_msg_type_number_t) inputStructCnt;
1491    }
1492    else {
1493	ool_input      = reinterpret_cast_mach_vm_address_t(inputStruct);
1494	ool_input_size = inputStructCnt;
1495    }
1496
1497    if (!outputCnt) {
1498	static uint32_t zero = 0;
1499	outputCnt = &zero;
1500    }
1501
1502    if (outputStructCntP) {
1503	size_t size = *outputStructCntP;
1504
1505	if (size <= sizeof(io_struct_inband_t)) {
1506	    inb_output      = outputStruct;
1507	    inb_output_size = (mach_msg_type_number_t) size;
1508	}
1509	else {
1510	    ool_output      = reinterpret_cast_mach_vm_address_t(outputStruct);
1511	    ool_output_size = (mach_vm_size_t)    size;
1512	}
1513    }
1514
1515    rtn = io_connect_async_method(connection,         wakePort,
1516				  reference,          referenceCnt,
1517				  selector,
1518				  (uint64_t *) input, inputCnt,
1519				  inb_input,          inb_input_size,
1520				  ool_input,          ool_input_size,
1521				  inb_output,         &inb_output_size,
1522				  output,             outputCnt,
1523				  ool_output,         &ool_output_size);
1524
1525    if (outputStructCntP) {
1526	if (*outputStructCntP <= sizeof(io_struct_inband_t))
1527	    *outputStructCntP = (size_t) inb_output_size;
1528	else
1529	    *outputStructCntP = (size_t) ool_output_size;
1530    }
1531
1532    return rtn;
1533}
1534
1535kern_return_t
1536IOConnectCallStructMethod(
1537	mach_port_t	 connection,		// In
1538	uint32_t	 selector,		// In
1539	const void	*inputStruct,		// In
1540	size_t		 inputStructCnt,	// In
1541	void		*outputStruct,		// Out
1542	size_t		*outputStructCnt)	// In/Out
1543{
1544    return IOConnectCallMethod(connection,   selector,
1545			       NULL,         0,
1546			       inputStruct,  inputStructCnt,
1547			       NULL,         NULL,
1548			       outputStruct, outputStructCnt);
1549}
1550
1551kern_return_t
1552IOConnectCallAsyncStructMethod(
1553	mach_port_t	 connection,		// In
1554	uint32_t	 selector,		// In
1555	mach_port_t	 wakePort,		// In
1556	uint64_t	*reference,		// In
1557	uint32_t	 referenceCnt,		// In
1558	const void	*inputStruct,		// In
1559	size_t		 inputStructCnt,	// In
1560	void		*outputStruct,		// Out
1561	size_t		*outputStructCnt)	// In/Out
1562{
1563    return IOConnectCallAsyncMethod(connection,   selector, wakePort,
1564				    reference,    referenceCnt,
1565				    NULL,         0,
1566				    inputStruct,  inputStructCnt,
1567				    NULL,         NULL,
1568				    outputStruct, outputStructCnt);
1569}
1570
1571kern_return_t
1572IOConnectCallScalarMethod(
1573	mach_port_t	 connection,		// In
1574	uint32_t	 selector,		// In
1575	const uint64_t	*input,			// In
1576	uint32_t	 inputCnt,		// In
1577	uint64_t	*output,		// Out
1578	uint32_t	*outputCnt)		// In/Out
1579{
1580    return IOConnectCallMethod(connection, selector,
1581			       input,      inputCnt,
1582			       NULL,       0,
1583			       output,     outputCnt,
1584			       NULL,       NULL);
1585}
1586
1587kern_return_t
1588IOConnectCallAsyncScalarMethod(
1589	mach_port_t	 connection,		// In
1590	uint32_t	 selector,		// In
1591	mach_port_t	 wakePort,		// In
1592	uint64_t	*reference,		// In
1593	uint32_t	 referenceCnt,		// In
1594	const uint64_t	*input,			// In
1595	uint32_t	 inputCnt,		// In
1596	uint64_t	*output,		// Out
1597	uint32_t	*outputCnt)		// In/Out
1598{
1599    return IOConnectCallAsyncMethod(connection, selector, wakePort,
1600				    reference,  referenceCnt,
1601				    input,      inputCnt,
1602				    NULL,       0,
1603				    output,    outputCnt,
1604				    NULL,      NULL);
1605}
1606
1607/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1608
1609kern_return_t
1610IOConnectTrap0(io_connect_t	connect,
1611	       uint32_t		index)
1612{
1613    return iokit_user_client_trap(connect, index, 0, 0, 0, 0, 0, 0);
1614}
1615
1616kern_return_t
1617IOConnectTrap1(io_connect_t	connect,
1618	       uint32_t		index,
1619	       uintptr_t	p1 )
1620{
1621    return iokit_user_client_trap(connect, index, p1, 0, 0, 0, 0, 0);
1622}
1623
1624kern_return_t
1625IOConnectTrap2(io_connect_t	connect,
1626	       uint32_t		index,
1627	       uintptr_t	p1,
1628	       uintptr_t	p2 )
1629{
1630    return iokit_user_client_trap(connect, index, p1, p2, 0, 0, 0, 0);
1631}
1632
1633kern_return_t
1634IOConnectTrap3(io_connect_t	connect,
1635	       uint32_t		index,
1636	       uintptr_t	p1,
1637	       uintptr_t	p2,
1638	       uintptr_t	p3 )
1639{
1640    return iokit_user_client_trap(connect, index, p1, p2, p3, 0, 0, 0);
1641}
1642
1643kern_return_t
1644IOConnectTrap4(io_connect_t	connect,
1645	       uint32_t		index,
1646	       uintptr_t	p1,
1647	       uintptr_t	p2,
1648	       uintptr_t	p3,
1649	       uintptr_t	p4 )
1650{
1651    return iokit_user_client_trap(connect, index, p1, p2, p3, p4, 0, 0);
1652}
1653
1654kern_return_t
1655IOConnectTrap5(io_connect_t	connect,
1656	       uint32_t		index,
1657	       uintptr_t	p1,
1658	       uintptr_t	p2,
1659	       uintptr_t	p3,
1660	       uintptr_t	p4,
1661	       uintptr_t	p5 )
1662{
1663    return iokit_user_client_trap(connect, index, p1, p2, p3, p4, p5, 0);
1664}
1665
1666kern_return_t
1667IOConnectTrap6(io_connect_t	connect,
1668	       uint32_t		index,
1669	       uintptr_t	p1,
1670	       uintptr_t	p2,
1671	       uintptr_t	p3,
1672	       uintptr_t	p4,
1673	       uintptr_t	p5,
1674	       uintptr_t	p6 )
1675{
1676    return iokit_user_client_trap(connect, index, p1, p2, p3, p4, p5, p6);
1677}
1678
1679/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1680
1681kern_return_t
1682IOConnectSetCFProperties(
1683	io_connect_t	connect,
1684	CFTypeRef	properties )
1685{
1686    CFDataRef		data;
1687    kern_return_t	kr;
1688    kern_return_t	result;
1689
1690    data = IOCFSerialize( properties, kNilOptions );
1691    if( !data)
1692	return( kIOReturnUnsupported );
1693
1694    kr = io_connect_set_properties( connect,
1695            (char *) CFDataGetBytePtr(data), CFDataGetLength(data),
1696            &result );
1697
1698    CFRelease(data);
1699
1700    if( KERN_SUCCESS == kr)
1701        kr = result;
1702
1703    return( kr );
1704}
1705
1706kern_return_t
1707IOConnectSetCFProperty(
1708	io_connect_t	connect,
1709        CFStringRef	propertyName,
1710	CFTypeRef	property )
1711{
1712    CFDictionaryRef	dict;
1713    kern_return_t	kr;
1714
1715    CFTypeRef name = propertyName;
1716    dict = CFDictionaryCreate( kCFAllocatorDefault,
1717		    &name, &property, 1,
1718		    &kCFTypeDictionaryKeyCallBacks,
1719		    &kCFTypeDictionaryValueCallBacks );
1720    if( !dict)
1721	return( kIOReturnNoMemory );
1722
1723    kr = IOConnectSetCFProperties( connect, dict );
1724    CFRelease( dict );
1725
1726    return( kr );
1727}
1728
1729
1730/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1731
1732/*
1733 * IORegistry accessors
1734 */
1735
1736kern_return_t
1737IORegistryCreateIterator(
1738        mach_port_t	_masterPort,
1739	const io_name_t	plane,
1740	IOOptionBits	options,
1741	io_iterator_t * iterator )
1742{
1743    kern_return_t	kr;
1744    mach_port_t		masterPort;
1745
1746    if (MACH_PORT_NULL == _masterPort)
1747	masterPort = __IOGetDefaultMasterPort();
1748    else
1749	masterPort = _masterPort;
1750
1751    kr = io_registry_create_iterator( masterPort, (char *) plane,
1752		options, iterator);
1753
1754    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
1755	mach_port_deallocate(mach_task_self(), masterPort);
1756
1757    return( kr );
1758}
1759
1760kern_return_t
1761IORegistryEntryCreateIterator(
1762	io_registry_entry_t	entry,
1763	const io_name_t		plane,
1764	IOOptionBits		options,
1765	io_iterator_t 	      * iterator )
1766{
1767    return( io_registry_entry_create_iterator( entry, (char *) plane,
1768		options, iterator));
1769}
1770
1771kern_return_t
1772IORegistryIteratorEnterEntry(
1773	io_iterator_t	iterator )
1774{
1775    return( io_registry_iterator_enter_entry( iterator));
1776}
1777
1778
1779kern_return_t
1780IORegistryIteratorExitEntry(
1781	io_iterator_t	iterator )
1782{
1783    return( io_registry_iterator_exit_entry( iterator));
1784}
1785
1786io_registry_entry_t
1787IORegistryEntryFromPath(
1788        mach_port_t		_masterPort,
1789	const io_string_t	path )
1790{
1791    kern_return_t	kr;
1792    io_registry_entry_t	entry;
1793    mach_port_t		masterPort;
1794
1795    if (MACH_PORT_NULL == _masterPort)
1796	masterPort = __IOGetDefaultMasterPort();
1797    else
1798	masterPort = _masterPort;
1799
1800    kr = io_registry_entry_from_path( masterPort, (char *) path, &entry );
1801    if( kIOReturnSuccess != kr)
1802	entry = 0;
1803
1804    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
1805	mach_port_deallocate(mach_task_self(), masterPort);
1806
1807    return( entry );
1808}
1809
1810io_registry_entry_t
1811IORegistryGetRootEntry(
1812        mach_port_t	_masterPort )
1813{
1814    kern_return_t	kr;
1815    mach_port_t		masterPort;
1816    io_registry_entry_t	entry;
1817
1818    if (MACH_PORT_NULL == _masterPort)
1819	masterPort = __IOGetDefaultMasterPort();
1820    else
1821	masterPort = _masterPort;
1822
1823    kr = io_registry_get_root_entry( masterPort, &entry );
1824    if( kIOReturnSuccess != kr)
1825	entry = 0;
1826
1827    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
1828	mach_port_deallocate(mach_task_self(), masterPort);
1829
1830    return( entry );
1831}
1832
1833kern_return_t
1834IORegistryEntryGetPath(
1835	io_registry_entry_t	entry,
1836	const io_name_t		plane,
1837	io_string_t		path )
1838{
1839    return( io_registry_entry_get_path( entry, (char *) plane, path ));
1840}
1841
1842boolean_t
1843IORegistryEntryInPlane(
1844	io_registry_entry_t	entry,
1845	const io_name_t 	plane )
1846{
1847    boolean_t		inPlane;
1848
1849    if( kIOReturnSuccess != io_registry_entry_in_plane(
1850		entry, (char *) plane, &inPlane ))
1851	inPlane = false;
1852
1853    return( inPlane );
1854}
1855
1856kern_return_t
1857IORegistryEntryGetName(
1858	io_registry_entry_t	entry,
1859	io_name_t 	        name )
1860{
1861    return( io_registry_entry_get_name( entry, name ));
1862}
1863
1864kern_return_t
1865IORegistryEntryGetNameInPlane(
1866	io_registry_entry_t	entry,
1867	const io_name_t 	plane,
1868	io_name_t 	        name )
1869{
1870    if( NULL == plane)
1871        plane = "";
1872    return( io_registry_entry_get_name_in_plane( entry,
1873						(char *) plane, name ));
1874}
1875
1876kern_return_t
1877IORegistryEntryGetLocationInPlane(
1878	io_registry_entry_t	entry,
1879	const io_name_t 	plane,
1880	io_name_t 	        location )
1881{
1882    if( NULL == plane)
1883        plane = "";
1884    return( io_registry_entry_get_location_in_plane( entry,
1885						(char *) plane, location ));
1886}
1887
1888kern_return_t
1889IORegistryEntryGetRegistryEntryID(
1890	io_registry_entry_t	entry,
1891	uint64_t *		entryID )
1892{
1893    kern_return_t kr;
1894
1895    kr =  io_registry_entry_get_registry_entry_id(entry, entryID);
1896    if (KERN_SUCCESS != kr)
1897	*entryID = 0;
1898
1899    return (kr);
1900}
1901
1902
1903kern_return_t
1904IORegistryEntryCreateCFProperties(
1905	io_registry_entry_t	entry,
1906	CFMutableDictionaryRef * properties,
1907        CFAllocatorRef		allocator,
1908	IOOptionBits   options __unused )
1909{
1910    kern_return_t 	kr;
1911    uint32_t	 	size;
1912    char *	 	propertiesBuffer;
1913    CFStringRef  	errorString;
1914    const char * 	cstr;
1915
1916    kr = io_registry_entry_get_properties(entry, &propertiesBuffer, &size);
1917    if (kr != kIOReturnSuccess) return kr;
1918
1919    *properties = (CFMutableDictionaryRef)
1920                        IOCFUnserialize(propertiesBuffer, allocator,
1921					0, &errorString);
1922    if (!(*properties) && errorString) {
1923
1924        if ((cstr = CFStringGetCStringPtr(errorString,
1925					kCFStringEncodingMacRoman)))
1926            printf("%s\n", cstr);
1927	CFRelease(errorString);
1928    }
1929
1930    // free propertiesBuffer !
1931    vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size);
1932
1933    return( *properties ? kIOReturnSuccess : kIOReturnInternalError );
1934}
1935
1936CFTypeRef
1937IORegistryEntryCreateCFProperty(
1938	io_registry_entry_t	entry,
1939	CFStringRef		key,
1940        CFAllocatorRef		allocator,
1941	IOOptionBits   options __unused )
1942{
1943    IOReturn		kr;
1944    CFTypeRef		type;
1945    uint32_t	 	size;
1946    char *	 	propertiesBuffer;
1947    CFStringRef  	errorString;
1948    const char *    	cStr;
1949    char *	    	buffer = NULL;
1950
1951    cStr = CFStringGetCStringPtr( key, kCFStringEncodingMacRoman);
1952    if( !cStr) {
1953	CFIndex bufferSize = CFStringGetMaximumSizeForEncoding( CFStringGetLength(key),
1954	       kCFStringEncodingMacRoman) + sizeof('\0');
1955        buffer = malloc( bufferSize);
1956        if( buffer && CFStringGetCString( key, buffer, bufferSize, kCFStringEncodingMacRoman))
1957            cStr = buffer;
1958    }
1959
1960    if( cStr)
1961        kr = io_registry_entry_get_property(entry, (char *) cStr, &propertiesBuffer, &size);
1962    else
1963        kr = kIOReturnError;
1964
1965    if( buffer)
1966        free( buffer);
1967
1968    if( kr != kIOReturnSuccess)
1969        return( NULL );
1970
1971    type = (CFMutableDictionaryRef)
1972                        IOCFUnserialize(propertiesBuffer, allocator,
1973					0, &errorString);
1974    if (!type && errorString) {
1975
1976        if ((cStr = CFStringGetCStringPtr(errorString,
1977					kCFStringEncodingMacRoman)))
1978            printf("%s\n", cStr);
1979	CFRelease(errorString);
1980    }
1981
1982    // free propertiesBuffer !
1983    vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size);
1984
1985    return( type );
1986}
1987
1988CFTypeRef
1989IORegistryEntrySearchCFProperty(
1990	io_registry_entry_t	entry,
1991	const io_name_t		plane,
1992	CFStringRef		key,
1993        CFAllocatorRef		allocator,
1994	IOOptionBits		options )
1995{
1996    IOReturn		kr;
1997    CFTypeRef		type;
1998    uint32_t	 	size;
1999    char *	 	propertiesBuffer;
2000    CFStringRef  	errorString;
2001    const char *    	cStr;
2002    char *	    	buffer = NULL;
2003
2004    cStr = CFStringGetCStringPtr( key, kCFStringEncodingMacRoman);
2005    if( !cStr) {
2006	CFIndex bufferSize = CFStringGetMaximumSizeForEncoding( CFStringGetLength(key),
2007	       kCFStringEncodingMacRoman) + sizeof('\0');
2008        buffer = malloc( bufferSize);
2009        if( buffer && CFStringGetCString( key, buffer, bufferSize, kCFStringEncodingMacRoman))
2010            cStr = buffer;
2011    }
2012
2013    if( cStr)
2014        kr = io_registry_entry_get_property_recursively(entry, (char *) plane, (char *) cStr,
2015                                                        options, &propertiesBuffer, &size);
2016    else
2017        kr = kIOReturnError;
2018
2019    if( buffer)
2020        free( buffer);
2021
2022    if( kr != kIOReturnSuccess)
2023        return( NULL );
2024
2025    type = (CFMutableDictionaryRef)
2026                        IOCFUnserialize(propertiesBuffer, allocator,
2027					0, &errorString);
2028    if (!type && errorString) {
2029
2030        if ((cStr = CFStringGetCStringPtr(errorString,
2031					kCFStringEncodingMacRoman)))
2032            printf("%s\n", cStr);
2033	CFRelease(errorString);
2034    }
2035
2036    // free propertiesBuffer !
2037    vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size);
2038
2039    return( type );
2040}
2041
2042kern_return_t
2043IORegistryEntryGetProperty(
2044	io_registry_entry_t	entry,
2045	const io_name_t		name,
2046	io_struct_inband_t	buffer,
2047	uint32_t	      * size )
2048{
2049    return( io_registry_entry_get_property_bytes( entry, (char *) name,
2050						  buffer, size ));
2051}
2052
2053
2054kern_return_t
2055IORegistryEntrySetCFProperties(
2056	io_registry_entry_t	entry,
2057	CFTypeRef	 	properties )
2058{
2059    CFDataRef		data;
2060    kern_return_t	kr;
2061    kern_return_t	result;
2062
2063    data = IOCFSerialize( properties, kNilOptions );
2064    if( !data)
2065	return( kIOReturnUnsupported );
2066
2067    kr = io_registry_entry_set_properties( entry,
2068            (char *) CFDataGetBytePtr(data), CFDataGetLength(data),
2069            &result );
2070
2071    CFRelease(data);
2072
2073    if( KERN_SUCCESS == kr)
2074        kr = result;
2075
2076    return( kr );
2077}
2078
2079kern_return_t
2080IORegistryEntrySetCFProperty(
2081	io_registry_entry_t	entry,
2082        CFStringRef		propertyName,
2083	CFTypeRef	 	property )
2084{
2085    CFDictionaryRef	dict;
2086    kern_return_t	kr;
2087
2088    dict = CFDictionaryCreate( kCFAllocatorDefault,
2089                                (const void **) &propertyName, (const void **) &property, 1,
2090                                &kCFTypeDictionaryKeyCallBacks,
2091                                &kCFTypeDictionaryValueCallBacks );
2092    if( !dict)
2093	return( kIOReturnNoMemory );
2094
2095    kr = IORegistryEntrySetCFProperties( entry, dict );
2096    CFRelease( dict );
2097
2098    return( kr );
2099}
2100
2101kern_return_t
2102IORegistryEntryGetChildIterator(
2103	io_registry_entry_t	entry,
2104	const io_name_t		plane,
2105	io_iterator_t	      * iterator )
2106{
2107    return( io_registry_entry_get_child_iterator( entry,
2108						(char *) plane, iterator));
2109}
2110
2111kern_return_t
2112IORegistryEntryGetParentIterator(
2113	io_registry_entry_t	entry,
2114	const io_name_t		plane,
2115	io_iterator_t	      * iterator )
2116{
2117    return( io_registry_entry_get_parent_iterator( entry,
2118						(char *) plane, iterator));
2119}
2120
2121kern_return_t
2122IORegistryEntryGetChildEntry(
2123	io_registry_entry_t	entry,
2124	const io_name_t		plane,
2125	io_registry_entry_t   * child )
2126{
2127    kern_return_t       kr;
2128    io_iterator_t	iter;
2129
2130    kr = IORegistryEntryGetChildIterator( entry, plane, &iter );
2131
2132    if( KERN_SUCCESS == kr) {
2133
2134	*child = IOIteratorNext( iter );
2135	IOObjectRelease( iter );
2136	if( MACH_PORT_NULL == *child)
2137	    kr = kIOReturnNoDevice;
2138    }
2139
2140    return( kr );
2141}
2142
2143kern_return_t
2144IORegistryEntryGetParentEntry(
2145	io_registry_entry_t	entry,
2146	const io_name_t		plane,
2147	io_registry_entry_t   * parent )
2148{
2149    kern_return_t       kr;
2150    io_iterator_t	iter;
2151
2152    kr = IORegistryEntryGetParentIterator( entry, plane, &iter );
2153
2154    if( KERN_SUCCESS == kr) {
2155
2156	*parent = IOIteratorNext( iter );
2157	IOObjectRelease( iter );
2158	if( MACH_PORT_NULL == *parent)
2159	    kr = kIOReturnNoDevice;
2160    }
2161
2162    return( kr );
2163}
2164/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2165
2166kern_return_t
2167IOServiceOFPathToBSDName(mach_port_t	 masterPort,
2168                         const io_name_t openFirmwarePath,
2169                         io_name_t   	 bsdName)
2170{
2171    kern_return_t       kr;
2172    io_registry_entry_t service;
2173    io_iterator_t       services;
2174
2175    // Initialize return values.
2176
2177    bsdName[0] = 0;
2178
2179    // Find objects matching the given open firmware name.
2180
2181    kr = IOServiceGetMatchingServices(
2182             /* mach_port_t   */ masterPort,
2183             /* void *        */ IOOpenFirmwarePathMatching(
2184                                     /* mach_port_t  */ masterPort,
2185                                     /* uint32_t     */ 0,
2186                                     /* const char * */ openFirmwarePath ),
2187             /* io_iterator * */ &services );
2188
2189    if( KERN_SUCCESS != kr )  return( kr );
2190
2191    // Obtain the first (and presumably the only) match.
2192
2193    service = IOIteratorNext( services );
2194
2195    if( service ) {
2196
2197        // Obtain the BSD name property from this object.
2198
2199        uint32_t bsdNameSize = sizeof(io_name_t);
2200
2201        kr = IORegistryEntryGetProperty(
2202                 /* mach_port_t        */ service,
2203                 /* io_name_t          */ kIOBSDNameKey,
2204                 /* io_struct_inband_t */ bsdName,
2205                 /* uint32_t *         */ &bsdNameSize);
2206
2207        if( KERN_SUCCESS != kr )  bsdName[0] = 0;
2208
2209        IOObjectRelease( service );
2210    }
2211    else {
2212        kr = KERN_FAILURE;
2213    }
2214
2215    IOObjectRelease( services );
2216
2217    return kr;
2218}
2219
2220/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2221
2222kern_return_t
2223IOCatalogueSendData(
2224        mach_port_t		_masterPort,
2225        uint32_t                flag,
2226        const char             *buffer,
2227        uint32_t                size )
2228{
2229    kern_return_t kr;
2230    kern_return_t result;
2231    mach_port_t   masterPort;
2232
2233    if (MACH_PORT_NULL == _masterPort)
2234	masterPort = __IOGetDefaultMasterPort();
2235    else
2236	masterPort = _masterPort;
2237
2238    kr = io_catalog_send_data( masterPort, flag,
2239                            (char *) buffer, size, &result );
2240    if( KERN_SUCCESS == kr)
2241        kr = result;
2242
2243    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2244	mach_port_deallocate(mach_task_self(), masterPort);
2245
2246    return( kr );
2247}
2248
2249kern_return_t
2250IOCatalogueTerminate(
2251        mach_port_t		_masterPort,
2252        uint32_t                flag,
2253        io_name_t		description )
2254{
2255    kern_return_t	kr;
2256    mach_port_t		masterPort;
2257
2258    if (MACH_PORT_NULL == _masterPort)
2259	masterPort = __IOGetDefaultMasterPort();
2260    else
2261	masterPort = _masterPort;
2262
2263    kr = io_catalog_terminate( masterPort, flag, description );
2264
2265    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2266	mach_port_deallocate(mach_task_self(), masterPort);
2267
2268    return( kr );
2269}
2270
2271kern_return_t
2272IOCatalogueGetData(
2273        mach_port_t		_masterPort,
2274        uint32_t                flag,
2275        char                  **buffer,
2276        uint32_t               *size )
2277{
2278    kern_return_t	kr;
2279    mach_port_t		masterPort;
2280
2281    if (MACH_PORT_NULL == _masterPort)
2282	masterPort = __IOGetDefaultMasterPort();
2283    else
2284	masterPort = _masterPort;
2285
2286    kr = io_catalog_get_data( masterPort, flag, (char **)buffer, (unsigned *)size );
2287
2288    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2289	mach_port_deallocate(mach_task_self(), masterPort);
2290
2291    return( kr );
2292}
2293
2294kern_return_t
2295IOCatlogueGetGenCount(
2296        mach_port_t		_masterPort,
2297        uint32_t               *genCount )
2298{
2299    kern_return_t	kr;
2300    mach_port_t		masterPort;
2301
2302    if (MACH_PORT_NULL == _masterPort)
2303	masterPort = __IOGetDefaultMasterPort();
2304    else
2305	masterPort = _masterPort;
2306
2307    kr = io_catalog_get_gen_count( masterPort, genCount );
2308
2309    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2310	mach_port_deallocate(mach_task_self(), masterPort);
2311
2312    return( kr );
2313}
2314
2315kern_return_t
2316IOCatalogueModuleLoaded(
2317        mach_port_t		_masterPort,
2318        io_name_t               name )
2319{
2320    kern_return_t	kr;
2321    mach_port_t		masterPort;
2322
2323    if (MACH_PORT_NULL == _masterPort)
2324	masterPort = __IOGetDefaultMasterPort();
2325    else
2326	masterPort = _masterPort;
2327
2328    kr = io_catalog_module_loaded( masterPort, name );
2329
2330    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2331	mach_port_deallocate(mach_task_self(), masterPort);
2332
2333    return( kr );
2334}
2335
2336kern_return_t
2337IOCatalogueReset(
2338        mach_port_t		_masterPort,
2339	uint32_t		flag )
2340{
2341    kern_return_t	kr;
2342    mach_port_t		masterPort;
2343
2344    if (MACH_PORT_NULL == _masterPort)
2345	masterPort = __IOGetDefaultMasterPort();
2346    else
2347	masterPort = _masterPort;
2348
2349    kr = io_catalog_reset(masterPort, flag);
2350
2351    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2352	mach_port_deallocate(mach_task_self(), masterPort);
2353
2354    return( kr );
2355}
2356
2357/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2358
2359// obsolete API
2360
2361kern_return_t
2362IORegistryCreateEnumerator(
2363        mach_port_t	_masterPort,
2364	mach_port_t *	enumerator )
2365{
2366    kern_return_t	kr;
2367    mach_port_t		masterPort;
2368
2369    if (MACH_PORT_NULL == _masterPort)
2370	masterPort = __IOGetDefaultMasterPort();
2371    else
2372	masterPort = _masterPort;
2373
2374    kr = io_registry_create_iterator( masterPort,
2375                                         "IOService", true, enumerator );
2376
2377    if ((masterPort != MACH_PORT_NULL) && (masterPort != _masterPort))
2378	mach_port_deallocate(mach_task_self(), masterPort);
2379
2380    return( kr );
2381}
2382
2383kern_return_t
2384IORegistryEnumeratorReset(
2385	mach_port_t	enumerator )
2386{
2387    return( io_iterator_reset( enumerator));
2388}
2389
2390
2391static io_object_t lastRegIter;
2392
2393kern_return_t
2394IORegistryEnumeratorNextConforming(
2395	mach_port_t	enumerator,
2396	const char *	name,
2397	boolean_t recursive __unused )
2398{
2399    io_object_t	next 	= 0;
2400
2401    while( (next = IOIteratorNext( enumerator ))) {
2402
2403	if( IOObjectConformsTo( next, (char *) name ))
2404	    break;
2405
2406	IOObjectRelease( next );
2407    }
2408
2409    lastRegIter = next;
2410
2411    return( next ? kIOReturnSuccess : kIOReturnNoDevice );
2412}
2413
2414
2415#if 0
2416kern_return_t
2417IORegistryGetProperties(
2418	mach_port_t	enumerator ,
2419	void **		properties )
2420{
2421    return( IORegistryEntryGetProperties( lastRegIter,
2422		(struct IOObject **)properties));
2423}
2424#endif
2425
2426kern_return_t
2427IOOpenConnection(
2428	mach_port_t enumerator __unused,
2429	task_port_t	owningTask,
2430	uint32_t	type,
2431	mach_port_t *	connect )
2432{
2433    kern_return_t	kr;
2434
2435    kr = IOServiceOpen( lastRegIter,
2436	owningTask, type, connect );
2437
2438    IOObjectRelease( lastRegIter );
2439
2440    return( kr );
2441}
2442
2443
2444kern_return_t
2445IOCloseConnection(
2446	mach_port_t	connect )
2447{
2448    return( io_service_close( connect));
2449}
2450
2451
2452kern_return_t
2453IOSetNotificationPort(
2454	mach_port_t	connect,
2455	uint32_t	type,
2456	mach_port_t	port )
2457{
2458    return( io_connect_set_notification_port( connect, type, port, 0));
2459}
2460kern_return_t
2461IORegisterClient(
2462	mach_port_t	connect,
2463	mach_port_t	client )
2464{
2465    return( io_connect_add_client( connect, client));
2466}
2467
2468kern_return_t
2469IORegistryDisposeEnumerator(
2470	io_enumerator_t	enumerator )
2471{
2472    return( IOObjectRelease( enumerator ));
2473}
2474
2475/* -------------------------- */
2476
2477kern_return_t
2478IOCompatibiltyNumber(
2479	mach_port_t connect __unused,
2480	uint32_t *	objectNumber )
2481{
2482	*objectNumber = 1;
2483	return( kIOReturnSuccess);
2484}
2485
2486
2487void
2488IOInitContainerClasses()
2489{
2490}
2491
2492/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2493
2494/* 32bit binary compatibility routines for deprecated APIs */
2495#if !defined(__LP64__)
2496
2497// Compatability routines with 32bit IOKitLib
2498kern_return_t
2499IOConnectMethodScalarIScalarO(
2500	io_connect_t	connect,
2501	uint32_t	index,
2502	IOItemCount	inCount,
2503	IOItemCount	scalarOutputCount,
2504	... )
2505{
2506    uint64_t		inData[6], outData[6];
2507    kern_return_t	err;
2508    uint32_t		i, outCount;
2509    va_list		val;
2510
2511    if (inCount + scalarOutputCount > 6)
2512	return MIG_ARRAY_TOO_LARGE;
2513
2514    va_start(val, scalarOutputCount);
2515    for (i = 0; i < inCount; i++)
2516	inData[i] = va_arg(val, uint32_t);
2517
2518    outCount = scalarOutputCount;
2519    err = IOConnectCallScalarMethod(connect, index,
2520	    inData, inCount, outData, &outCount);
2521
2522    if( kIOReturnSuccess == err) {
2523	for (i = 0; i < outCount; i++) {
2524	    uint32_t *out = va_arg(val, uint32_t *);
2525	    *out = (uint32_t) outData[i];
2526	}
2527    }
2528    va_end(val);
2529
2530    return err;
2531}
2532
2533kern_return_t
2534IOConnectMethodScalarIStructureO(
2535	io_connect_t	connect,
2536	uint32_t	index,
2537	IOItemCount	inCount,
2538	IOByteCount *	outSizeP,
2539	... )
2540{
2541    uint64_t		inData[6];
2542    void               *out = NULL;
2543    IOItemCount		i;
2544    va_list		val;
2545
2546    if (inCount > 6)
2547	return MIG_ARRAY_TOO_LARGE;
2548
2549    va_start(val, outSizeP);
2550    for (i = 0; i < inCount; i++)
2551	inData[i] = va_arg(val, uint32_t);
2552    if (outSizeP && *outSizeP)
2553	out = va_arg(val, void *);
2554
2555    kern_return_t err = IOConnectCallMethod(connect, index,
2556	    inData, inCount, NULL, 0,
2557	    NULL,   0,       out,  outSizeP);
2558
2559    va_end(val);
2560
2561    return err;
2562}
2563
2564kern_return_t
2565IOConnectMethodScalarIStructureI(
2566	io_connect_t	connect,
2567	uint32_t	index,
2568	IOItemCount	inCount,
2569	IOByteCount	inSize,
2570	... )
2571{
2572    uint64_t		inData[6];
2573    uint8_t            *in = NULL;
2574    va_list		val;
2575
2576    if (inCount > 6)
2577	return MIG_ARRAY_TOO_LARGE;
2578
2579    va_start(val, inSize);
2580    for (IOItemCount i = 0; i < inCount; i++)
2581	inData[i] = va_arg(val, uint32_t);
2582    if (inSize)
2583	in = va_arg(val, void *);
2584
2585    kern_return_t err = IOConnectCallMethod(connect, index,
2586	    inData, inCount, in,   inSize,
2587	    NULL,   NULL,    NULL, NULL);
2588
2589    va_end(val);
2590
2591    return err;
2592}
2593
2594kern_return_t
2595IOConnectMethodStructureIStructureO(
2596	io_connect_t	connect,
2597	uint32_t	index,
2598	IOItemCount	inSize,
2599	IOByteCount *	outSizeP,
2600	void *		in,
2601	void *		out )
2602{
2603    return IOConnectCallStructMethod(connect, index, in, inSize, out, outSizeP);
2604}
2605
2606kern_return_t
2607IOMapMemory(
2608	io_connect_t	connect,
2609	uint32_t	memoryType,
2610	task_port_t	intoTask,
2611	vm_address_t *	atAddress,
2612	vm_size_t    *	ofSize,
2613	uint32_t	flags )
2614{
2615    return( io_connect_map_memory( connect, memoryType, intoTask,
2616	atAddress, ofSize, flags));
2617}
2618
2619#if EMULATE_IOCONNECT_64 || EMULATE_IOCONNECT_ASYNC_64
2620
2621// ILP32 - need to remap up to 64 bit scalars these are helpers
2622#define arrayCnt(type)	(sizeof(type)/sizeof(type[0]))
2623static void inflate_vec(uint64_t *dp, int d, int *sp, int s)
2624{
2625    if (d > s)
2626	d = s;
2627
2628    for (int i = 0; i < d; i++)
2629	dp[i] = (uint32_t) sp[i];
2630}
2631
2632static void deflate_vec(int *dp, int d, uint64_t *sp, int s)
2633{
2634    if (d > s)
2635	d = s;
2636
2637    for (int i = 0; i < d; i++)
2638	dp[i] = (int) sp[i];
2639}
2640#endif // EMULATE_IOCONNECT_64 || EMULATE_IOCONNECT_ASYNC_64
2641
2642#if EMULATE_IOCONNECT_64
2643kern_return_t io_connect_method
2644(
2645     mach_port_t connection,
2646     uint32_t selector,
2647     io_scalar_inband64_t input,
2648     mach_msg_type_number_t inputCnt,
2649     io_struct_inband_t inband_input,
2650     mach_msg_type_number_t inband_inputCnt,
2651     mach_vm_address_t ool_input,
2652     mach_vm_size_t  ool_input_size __unused,
2653     io_scalar_inband64_t output,
2654     mach_msg_type_number_t *outputCnt,
2655     io_struct_inband_t inband_output,
2656     mach_msg_type_number_t *inband_outputCnt,
2657     mach_vm_address_t ool_output,
2658     mach_vm_size_t * ool_output_size __unused
2659)
2660{
2661    if (ool_input || ool_output)
2662	return MIG_ARRAY_TOO_LARGE;
2663
2664    if (inband_input && inband_output) {
2665	// io_connect_method_structureI_structureO
2666	return io_connect_method_structureI_structureO(connection, selector,
2667		inband_input, inband_inputCnt, inband_output, inband_outputCnt);
2668    }
2669
2670    io_scalar_inband_t inData;
2671    deflate_vec(inData, arrayCnt(inData), input, inputCnt);
2672
2673    if (inband_input) {
2674	// io_connect_method_scalarI_structureI
2675	return io_connect_method_scalarI_structureI(connection, selector,
2676		inData, inputCnt, inband_input, inband_inputCnt);
2677    }
2678    else if (inband_output) {
2679	// io_connect_method_scalarI_structureO
2680	return io_connect_method_scalarI_structureO(connection, selector,
2681		inData, inputCnt, inband_output, inband_outputCnt);
2682    }
2683
2684    // io_connect_method_scalarI_scalarO
2685    kern_return_t rtn = io_connect_method_scalarI_scalarO(connection, selector,
2686	    inData, inputCnt, inData, outputCnt);
2687    inputCnt = (rtn == KERN_SUCCESS && outputCnt)? *outputCnt : 0;
2688    inflate_vec(output, inputCnt, inData, arrayCnt(inData));
2689    return rtn;
2690}
2691#endif // EMULATE_IOCONNECT_64
2692
2693#if EMULATE_IOCONNECT_ASYNC_64
2694kern_return_t io_connect_async_method
2695(
2696    mach_port_t connection,
2697    mach_port_t wake_port,
2698    io_async_ref64_t reference,
2699    mach_msg_type_number_t referenceCnt,
2700    uint32_t selector,
2701    io_scalar_inband64_t input,
2702    mach_msg_type_number_t inputCnt,
2703    io_struct_inband_t inband_input,
2704    mach_msg_type_number_t inband_inputCnt,
2705    mach_vm_address_t ool_input,
2706    mach_vm_size_t  ool_input_size __unused,
2707    io_scalar_inband64_t output,
2708    mach_msg_type_number_t *outputCnt,
2709    io_struct_inband_t inband_output,
2710    mach_msg_type_number_t *inband_outputCnt,
2711    mach_vm_address_t ool_output,
2712    mach_vm_size_t * ool_output_size __unused
2713)
2714{
2715    if (ool_input || ool_output)
2716	return MIG_ARRAY_TOO_LARGE;
2717
2718    io_async_ref_t refData;
2719    deflate_vec((int*)refData, arrayCnt(refData), reference, referenceCnt);
2720
2721    if (inband_input && inband_output) {
2722	// io_async_method_structureI_structureO
2723	return io_async_method_structureI_structureO(
2724		connection, wake_port, refData, referenceCnt, selector,
2725		inband_input, inband_inputCnt, inband_output, inband_outputCnt);
2726    }
2727
2728    io_scalar_inband_t inData;
2729    deflate_vec(inData, arrayCnt(inData), input, inputCnt);
2730
2731    if (inband_input) {
2732	// io_async_method_scalarI_structureI
2733	return io_async_method_scalarI_structureI(
2734		connection, wake_port, refData, referenceCnt, selector,
2735		inData, inputCnt, inband_input, inband_inputCnt);
2736    }
2737    else if (inband_output) {
2738	// io_async_method_scalarI_structureO
2739	return io_async_method_scalarI_structureO(
2740		connection, wake_port, refData, referenceCnt, selector,
2741		inData, inputCnt, inband_output, inband_outputCnt);
2742    }
2743
2744    // io_async_method_scalarI_scalarO
2745    kern_return_t rtn = io_async_method_scalarI_scalarO(
2746	    connection, wake_port, refData, referenceCnt, selector,
2747	    inData, inputCnt, inData, outputCnt);
2748    inputCnt = (rtn == KERN_SUCCESS && outputCnt)? *outputCnt : 0;
2749    inflate_vec(output, inputCnt, inData, arrayCnt(inData));
2750    return rtn;
2751}
2752#endif // EMULATE_IOCONNECT_ASYNC_64
2753
2754
2755#endif /* !__LP64__ */
2756
2757/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2758
2759__private_extern__ IOReturn
2760readFile(const char *path, vm_address_t * objAddr, vm_size_t * objSize)
2761{
2762    int fd;
2763    int err;
2764    struct stat stat_buf;
2765
2766    *objAddr = 0;
2767    *objSize = 0;
2768
2769    if((fd = open(path, O_RDONLY)) == -1)
2770	return errno;
2771
2772    do {
2773	if(fstat(fd, &stat_buf) == -1) {
2774	    err = errno;
2775	    continue;
2776	}
2777        if (0 == (stat_buf.st_mode & S_IFREG))
2778        {
2779            *objAddr = 0;
2780            *objSize = 0;
2781            err = kIOReturnNotReadable;
2782            continue;
2783        }
2784	*objSize = stat_buf.st_size;
2785
2786	*objAddr = (vm_address_t) mmap(NULL, round_page(stat_buf.st_size), PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
2787	if(!*objAddr) {
2788            *objSize = 0;
2789	    err = errno;
2790	    continue;
2791	}
2792
2793	err = kIOReturnSuccess;
2794
2795    } while( false );
2796
2797    close(fd);
2798
2799    return( err );
2800}
2801
2802__private_extern__ CFMutableDictionaryRef
2803readPlist( const char * path, UInt32 key __unused )
2804{
2805    IOReturn			err;
2806    vm_offset_t 		bytes;
2807    vm_size_t			byteLen;
2808    CFDataRef			data;
2809    CFMutableDictionaryRef	obj = 0;
2810
2811    err = readFile( path, &bytes, &byteLen );
2812
2813    if( kIOReturnSuccess != err)
2814	return (0);
2815
2816    data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault,
2817				(const UInt8 *) bytes, byteLen, kCFAllocatorNull );
2818    if( data) {
2819	obj = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, data,
2820					    kCFPropertyListMutableContainers,
2821					    (CFStringRef *) NULL );
2822	CFRelease( data );
2823    }
2824    vm_deallocate( mach_task_self(), bytes, byteLen );
2825
2826    return (obj);
2827}
2828
2829__private_extern__ Boolean
2830writePlist( const char * path, CFMutableDictionaryRef dict, UInt32 key __unused )
2831{
2832    Boolean   result = false;
2833    CFDataRef data;
2834    CFIndex   length;
2835    int       fd = -1;
2836
2837    data = CFPropertyListCreateXMLData(kCFAllocatorDefault, dict);
2838
2839    if (data)
2840    {
2841	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH));
2842	result = (fd >= 0);
2843	if (result)
2844	{
2845	    if ((length = CFDataGetLength(data)))
2846		result = (length == write(fd, CFDataGetBytePtr(data), length));
2847	    close(fd);
2848	}
2849	CFRelease(data);
2850    }
2851
2852    return (result);
2853}
2854
2855/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2856
2857#include <IOKit/IOSharedLock.h>
2858
2859boolean_t ev_try_lock(OSSpinLock * l)
2860{
2861    return OSSpinLockTry(l);
2862}
2863
2864void ev_unlock(OSSpinLock * l)
2865{
2866    OSSpinLockUnlock(l);
2867}
2868