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