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