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, ¬ify->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