1/* 2 * Copyright (c) 1998-2014 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#include <IOKit/IOCPU.h> 30#include <IOKit/IODeviceTreeSupport.h> 31#include <IOKit/IOKitDebug.h> 32#include <IOKit/IOMapper.h> 33#include <IOKit/IOMessage.h> 34#include <IOKit/IONVRAM.h> 35#include <IOKit/IOPlatformExpert.h> 36#include <IOKit/IORangeAllocator.h> 37#include <IOKit/IOWorkLoop.h> 38#include <IOKit/pwr_mgt/RootDomain.h> 39#include <IOKit/IOKitKeys.h> 40#include <IOKit/IOTimeStamp.h> 41#include <IOKit/IOUserClient.h> 42 43#include <IOKit/system.h> 44 45#include <libkern/c++/OSContainers.h> 46#include <libkern/crypto/sha1.h> 47#include <libkern/OSAtomic.h> 48 49extern "C" { 50#include <machine/machine_routines.h> 51#include <pexpert/pexpert.h> 52#include <uuid/uuid.h> 53} 54 55void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg); 56static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen); 57 58/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 59 60#define super IOService 61 62OSDefineMetaClassAndStructors(IOPlatformExpert, IOService) 63 64OSMetaClassDefineReservedUsed(IOPlatformExpert, 0); 65OSMetaClassDefineReservedUsed(IOPlatformExpert, 1); 66OSMetaClassDefineReservedUsed(IOPlatformExpert, 2); 67OSMetaClassDefineReservedUsed(IOPlatformExpert, 3); 68OSMetaClassDefineReservedUsed(IOPlatformExpert, 4); 69 70OSMetaClassDefineReservedUnused(IOPlatformExpert, 5); 71OSMetaClassDefineReservedUnused(IOPlatformExpert, 6); 72OSMetaClassDefineReservedUnused(IOPlatformExpert, 7); 73OSMetaClassDefineReservedUnused(IOPlatformExpert, 8); 74OSMetaClassDefineReservedUnused(IOPlatformExpert, 9); 75OSMetaClassDefineReservedUnused(IOPlatformExpert, 10); 76OSMetaClassDefineReservedUnused(IOPlatformExpert, 11); 77 78static IOPlatformExpert * gIOPlatform; 79static OSDictionary * gIOInterruptControllers; 80static IOLock * gIOInterruptControllersLock; 81static IODTNVRAM *gIOOptionsEntry; 82 83OSSymbol * gPlatformInterruptControllerName; 84 85/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 86 87bool IOPlatformExpert::attach( IOService * provider ) 88{ 89 90 if( !super::attach( provider )) 91 return( false); 92 93 return( true); 94} 95 96bool IOPlatformExpert::start( IOService * provider ) 97{ 98 IORangeAllocator * physicalRanges; 99 OSData * busFrequency; 100 uint32_t debugFlags; 101 102 if (!super::start(provider)) 103 return false; 104 105 // Override the mapper present flag is requested by boot arguments. 106 if (PE_parse_boot_argn("dart", &debugFlags, sizeof (debugFlags)) && (debugFlags == 0)) 107 removeProperty(kIOPlatformMapperPresentKey); 108 if (PE_parse_boot_argn("-x", &debugFlags, sizeof (debugFlags))) 109 removeProperty(kIOPlatformMapperPresentKey); 110 111 // Register the presence or lack thereof a system 112 // PCI address mapper with the IOMapper class 113 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey)); 114 115 gIOInterruptControllers = OSDictionary::withCapacity(1); 116 gIOInterruptControllersLock = IOLockAlloc(); 117 118 // Correct the bus frequency in the device tree. 119 busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4); 120 provider->setProperty("clock-frequency", busFrequency); 121 busFrequency->release(); 122 123 gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); 124 125 physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, 126 IORangeAllocator::kLocking); 127 assert(physicalRanges); 128 setProperty("Platform Memory Ranges", physicalRanges); 129 130 setPlatform( this ); 131 gIOPlatform = this; 132 133 PMInstantiatePowerDomains(); 134 135 // Parse the serial-number data and publish a user-readable string 136 OSData* mydata = (OSData*) (provider->getProperty("serial-number")); 137 if (mydata != NULL) { 138 OSString *serNoString = createSystemSerialNumberString(mydata); 139 if (serNoString != NULL) { 140 provider->setProperty(kIOPlatformSerialNumberKey, serNoString); 141 serNoString->release(); 142 } 143 } 144 145 return( configure(provider) ); 146} 147 148bool IOPlatformExpert::configure( IOService * provider ) 149{ 150 OSSet * topLevel; 151 OSDictionary * dict; 152 IOService * nub; 153 154 topLevel = OSDynamicCast( OSSet, getProperty("top-level")); 155 156 if( topLevel) { 157 while( (dict = OSDynamicCast( OSDictionary, 158 topLevel->getAnyObject()))) { 159 dict->retain(); 160 topLevel->removeObject( dict ); 161 nub = createNub( dict ); 162 if( 0 == nub) 163 continue; 164 dict->release(); 165 nub->attach( this ); 166 nub->registerService(); 167 } 168 } 169 170 return( true ); 171} 172 173IOService * IOPlatformExpert::createNub( OSDictionary * from ) 174{ 175 IOService * nub; 176 177 nub = new IOPlatformDevice; 178 if(nub) { 179 if( !nub->init( from )) { 180 nub->release(); 181 nub = 0; 182 } 183 } 184 return( nub); 185} 186 187bool IOPlatformExpert::compareNubName( const IOService * nub, 188 OSString * name, OSString ** matched ) const 189{ 190 return( nub->IORegistryEntry::compareName( name, matched )); 191} 192 193IOReturn IOPlatformExpert::getNubResources( IOService * nub ) 194{ 195 return( kIOReturnSuccess ); 196} 197 198long IOPlatformExpert::getBootROMType(void) 199{ 200 return _peBootROMType; 201} 202 203long IOPlatformExpert::getChipSetType(void) 204{ 205 return _peChipSetType; 206} 207 208long IOPlatformExpert::getMachineType(void) 209{ 210 return _peMachineType; 211} 212 213void IOPlatformExpert::setBootROMType(long peBootROMType) 214{ 215 _peBootROMType = peBootROMType; 216} 217 218void IOPlatformExpert::setChipSetType(long peChipSetType) 219{ 220 _peChipSetType = peChipSetType; 221} 222 223void IOPlatformExpert::setMachineType(long peMachineType) 224{ 225 _peMachineType = peMachineType; 226} 227 228bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/) 229{ 230 return( false ); 231} 232 233bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/) 234{ 235 return( false ); 236} 237 238OSString* IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty) 239{ 240 return NULL; 241} 242 243IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void) 244{ 245 return(OSDynamicCast(IORangeAllocator, 246 getProperty("Platform Memory Ranges"))); 247} 248 249int (*PE_halt_restart)(unsigned int type) = 0; 250 251int IOPlatformExpert::haltRestart(unsigned int type) 252{ 253 if (type == kPEPanicSync) return 0; 254 255 if (type == kPEHangCPU) while (true) {} 256 257 if (type == kPEUPSDelayHaltCPU) { 258 // RestartOnPowerLoss feature was turned on, proceed with shutdown. 259 type = kPEHaltCPU; 260 } 261 262 // On ARM kPEPanicRestartCPU is supported in the drivers 263 if (type == kPEPanicRestartCPU) 264 type = kPERestartCPU; 265 266 if (PE_halt_restart) return (*PE_halt_restart)(type); 267 else return -1; 268} 269 270void IOPlatformExpert::sleepKernel(void) 271{ 272#if 0 273 long cnt; 274 boolean_t intState; 275 276 intState = ml_set_interrupts_enabled(false); 277 278 for (cnt = 0; cnt < 10000; cnt++) { 279 IODelay(1000); 280 } 281 282 ml_set_interrupts_enabled(intState); 283#else 284// PE_initialize_console(0, kPEDisableScreen); 285 286 IOCPUSleepKernel(); 287 288// PE_initialize_console(0, kPEEnableScreen); 289#endif 290} 291 292long IOPlatformExpert::getGMTTimeOfDay(void) 293{ 294 return(0); 295} 296 297void IOPlatformExpert::setGMTTimeOfDay(long secs) 298{ 299} 300 301 302IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo ) 303{ 304 return( PE_current_console( consoleInfo)); 305} 306 307IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo, 308 unsigned int op) 309{ 310 return( PE_initialize_console( consoleInfo, op )); 311} 312 313IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController) 314{ 315 IOLockLock(gIOInterruptControllersLock); 316 317 gIOInterruptControllers->setObject(name, interruptController); 318 319 IOLockWakeup(gIOInterruptControllersLock, 320 gIOInterruptControllers, /* one-thread */ false); 321 322 IOLockUnlock(gIOInterruptControllersLock); 323 324 return kIOReturnSuccess; 325} 326 327IOReturn IOPlatformExpert::deregisterInterruptController(OSSymbol *name) 328{ 329 IOLockLock(gIOInterruptControllersLock); 330 331 gIOInterruptControllers->removeObject(name); 332 333 IOLockUnlock(gIOInterruptControllersLock); 334 335 return kIOReturnSuccess; 336} 337 338IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name) 339{ 340 OSObject *object; 341 342 IOLockLock(gIOInterruptControllersLock); 343 while (1) { 344 345 object = gIOInterruptControllers->getObject(name); 346 347 if (object != 0) 348 break; 349 350 IOLockSleep(gIOInterruptControllersLock, 351 gIOInterruptControllers, THREAD_UNINT); 352 } 353 354 IOLockUnlock(gIOInterruptControllersLock); 355 return OSDynamicCast(IOInterruptController, object); 356} 357 358 359void IOPlatformExpert::setCPUInterruptProperties(IOService *service) 360{ 361 IOCPUInterruptController *controller; 362 363 controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController"))); 364 if (controller) controller->setCPUInterruptProperties(service); 365} 366 367bool IOPlatformExpert::atInterruptLevel(void) 368{ 369 return ml_at_interrupt_context(); 370} 371 372bool IOPlatformExpert::platformAdjustService(IOService */*service*/) 373{ 374 return true; 375} 376 377void IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs) 378{ 379 *secs = getGMTTimeOfDay(); 380 *nsecs = 0; 381} 382 383void IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs) 384{ 385 setGMTTimeOfDay(secs); 386} 387 388 389//********************************************************************************* 390// PMLog 391// 392//********************************************************************************* 393 394void IOPlatformExpert:: 395PMLog(const char *who, unsigned long event, 396 unsigned long param1, unsigned long param2) 397{ 398 clock_sec_t nows; 399 clock_usec_t nowus; 400 clock_get_system_microtime(&nows, &nowus); 401 nowus += (nows % 1000) * 1000000; 402 403 kprintf("pm%u %p %.30s %d %lx %lx\n", 404 nowus, OBFUSCATE(current_thread()), who, // Identity 405 (int) event, (long)OBFUSCATE(param1), (long)OBFUSCATE(param2)); // Args 406} 407 408 409//********************************************************************************* 410// PMInstantiatePowerDomains 411// 412// In this vanilla implementation, a Root Power Domain is instantiated. 413// All other objects which register will be children of this Root. 414// Where this is inappropriate, PMInstantiatePowerDomains is overridden 415// in a platform-specific subclass. 416//********************************************************************************* 417 418void IOPlatformExpert::PMInstantiatePowerDomains ( void ) 419{ 420 root = new IOPMrootDomain; 421 root->init(); 422 root->attach(this); 423 root->start(this); 424} 425 426 427//********************************************************************************* 428// PMRegisterDevice 429// 430// In this vanilla implementation, all callers are made children of the root power domain. 431// Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass. 432//********************************************************************************* 433 434void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice) 435{ 436 root->addPowerChild ( theDevice ); 437} 438 439//********************************************************************************* 440// hasPMFeature 441// 442//********************************************************************************* 443 444bool IOPlatformExpert::hasPMFeature (unsigned long featureMask) 445{ 446 return ((_pePMFeatures & featureMask) != 0); 447} 448 449//********************************************************************************* 450// hasPrivPMFeature 451// 452//********************************************************************************* 453 454bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask) 455{ 456 return ((_pePrivPMFeatures & privFeatureMask) != 0); 457} 458 459//********************************************************************************* 460// numBatteriesSupported 461// 462//********************************************************************************* 463 464int IOPlatformExpert::numBatteriesSupported (void) 465{ 466 return (_peNumBatteriesSupported); 467} 468 469//********************************************************************************* 470// CheckSubTree 471// 472// This method is called by the instantiated sublass of the platform expert to 473// determine how a device should be inserted into the Power Domain. The subclass 474// provides an XML power tree description against which a device is matched based 475// on class and provider. If a match is found this routine returns true in addition 476// to flagging the description tree at the appropriate node that a device has been 477// registered for the given service. 478//********************************************************************************* 479 480bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent) 481{ 482 unsigned int i; 483 unsigned int numPowerTreeNodes; 484 OSDictionary * entry; 485 OSDictionary * matchingDictionary; 486 OSDictionary * providerDictionary; 487 OSDictionary * deviceDictionary; 488 OSDictionary * nubDictionary; 489 OSArray * children; 490 bool nodeFound = false; 491 bool continueSearch = false; 492 bool deviceMatch = false; 493 bool providerMatch = false; 494 bool multiParentMatch = false; 495 496 if ( (NULL == theDevice) || (NULL == inSubTree) ) 497 return false; 498 499 numPowerTreeNodes = inSubTree->getCount (); 500 501 // iterate through the power tree to find a home for this device 502 503 for ( i = 0; i < numPowerTreeNodes; i++ ) { 504 505 entry = (OSDictionary *) inSubTree->getObject (i); 506 507 matchingDictionary = (OSDictionary *) entry->getObject ("device"); 508 providerDictionary = (OSDictionary *) entry->getObject ("provider"); 509 510 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match 511 if ( matchingDictionary ) { 512 deviceMatch = false; 513 if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) { 514 deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary ); 515 deviceDictionary->release (); 516 } 517 } 518 519 providerMatch = true; // we indicate a match if there is no nub or provider 520 if ( theNub && providerDictionary ) { 521 providerMatch = false; 522 if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) { 523 providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary ); 524 nubDictionary->release (); 525 } 526 } 527 528 multiParentMatch = true; // again we indicate a match if there is no multi-parent node 529 if (deviceMatch && providerMatch) { 530 if (NULL != multipleParentKeyValue) { 531 OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent"); 532 multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false; 533 } 534 } 535 536 nodeFound = (deviceMatch && providerMatch && multiParentMatch); 537 538 // if the power tree specifies a provider dictionary but theNub is 539 // NULL then we cannot match with this entry. 540 541 if ( theNub == NULL && providerDictionary != NULL ) 542 nodeFound = false; 543 544 // if this node is THE ONE...then register the device 545 546 if ( nodeFound ) { 547 if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) { 548 549 if ( kIOLogPower & gIOKitDebug) 550 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n"); 551 552 numInstancesRegistered++; 553 554 // determine if we need to search for additional nodes for this item 555 multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent"); 556 } 557 else 558 nodeFound = false; 559 } 560 561 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) ); 562 563 if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) { 564 nodeFound = CheckSubTree ( children, theNub, theDevice, entry ); 565 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) ); 566 } 567 568 if ( false == continueSearch ) 569 break; 570 } 571 572 return ( nodeFound ); 573} 574 575//********************************************************************************* 576// RegisterServiceInTree 577// 578// Register a device at the specified node of our power tree. 579//********************************************************************************* 580 581bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider) 582{ 583 IOService * aService; 584 bool registered = false; 585 OSArray * children; 586 unsigned int numChildren; 587 OSDictionary * child; 588 589 // make sure someone is not already registered here 590 591 if ( NULL == theTreeNode->getObject ("service") ) { 592 593 if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) { 594 595 // 1. CHILDREN ------------------ 596 597 // we registered the node in the tree...now if the node has children 598 // registered we must tell this service to add them. 599 600 if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) { 601 numChildren = children->getCount (); 602 for ( unsigned int i = 0; i < numChildren; i++ ) { 603 if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) { 604 if ( NULL != (aService = (IOService *) child->getObject ("service")) ) 605 theService->addPowerChild (aService); 606 } 607 } 608 } 609 610 // 2. PARENT -------------------- 611 612 // also we must notify the parent of this node (if a registered service 613 // exists there) of a new child. 614 615 if ( theTreeParentNode ) { 616 if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) ) 617 if (aService != theProvider) 618 aService->addPowerChild (theService); 619 } 620 621 registered = true; 622 } 623 } 624 625 return registered; 626} 627 628//********************************************************************************* 629// printDictionaryKeys 630// 631// Print the keys for the given dictionary and selected contents. 632//********************************************************************************* 633void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg) 634{ 635 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary); 636 OSSymbol * mkey; 637 OSString * ioClass; 638 unsigned int i = 0; 639 640 mcoll->reset (); 641 642 mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ()); 643 644 while (mkey) { 645 646 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () ); 647 648 // if this is the IOClass key, print it's contents 649 650 if ( mkey->isEqualTo ("IOClass") ) { 651 ioClass = (OSString *) inDictionary->getObject ("IOClass"); 652 if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () ); 653 } 654 655 // if this is an IOProviderClass key print it 656 657 if ( mkey->isEqualTo ("IOProviderClass") ) { 658 ioClass = (OSString *) inDictionary->getObject ("IOProviderClass"); 659 if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () ); 660 661 } 662 663 // also print IONameMatch keys 664 if ( mkey->isEqualTo ("IONameMatch") ) { 665 ioClass = (OSString *) inDictionary->getObject ("IONameMatch"); 666 if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () ); 667 } 668 669 // also print IONameMatched keys 670 671 if ( mkey->isEqualTo ("IONameMatched") ) { 672 ioClass = (OSString *) inDictionary->getObject ("IONameMatched"); 673 if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () ); 674 } 675 676#if 0 677 // print clock-id 678 679 if ( mkey->isEqualTo ("AAPL,clock-id") ) { 680 char * cstr; 681 cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id")); 682 if (cstr) 683 kprintf (" ===> AAPL,clock-id is %s\n", cstr ); 684 } 685#endif 686 687 // print name 688 689 if ( mkey->isEqualTo ("name") ) { 690 char nameStr[64]; 691 nameStr[0] = 0; 692 getCStringForObject(inDictionary->getObject("name"), nameStr, 693 sizeof(nameStr)); 694 if (strlen(nameStr) > 0) 695 IOLog ("%s name is %s\n", inMsg, nameStr); 696 } 697 698 mkey = (OSSymbol *) mcoll->getNextObject (); 699 700 i++; 701 } 702 703 mcoll->release (); 704} 705 706static void 707getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen) 708{ 709 char * buffer; 710 unsigned int len, i; 711 712 if ( (NULL == inObj) || (NULL == outStr)) 713 return; 714 715 char * objString = (char *) (inObj->getMetaClass())->getClassName(); 716 717 if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) || 718 (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol")))) 719 strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen); 720 721 else if (0 == strncmp(objString, "OSData", sizeof("OSData"))) { 722 len = ((OSData *)inObj)->getLength(); 723 buffer = (char *)((OSData *)inObj)->getBytesNoCopy(); 724 if (buffer && (len > 0)) { 725 for (i=0; i < len; i++) { 726 outStr[i] = buffer[i]; 727 } 728 outStr[len] = 0; 729 } 730 } 731} 732 733/* IOShutdownNotificationsTimedOut 734 * - Called from a timer installed by PEHaltRestart 735 */ 736static void IOShutdownNotificationsTimedOut( 737 thread_call_param_t p0, 738 thread_call_param_t p1) 739{ 740 int type = (int)(long)p0; 741 742 /* 30 seconds has elapsed - resume shutdown */ 743 if(gIOPlatform) gIOPlatform->haltRestart(type); 744} 745 746 747extern "C" { 748 749/* 750 * Callouts from BSD for machine name & model 751 */ 752 753boolean_t PEGetMachineName( char * name, int maxLength ) 754{ 755 if( gIOPlatform) 756 return( gIOPlatform->getMachineName( name, maxLength )); 757 else 758 return( false ); 759} 760 761boolean_t PEGetModelName( char * name, int maxLength ) 762{ 763 if( gIOPlatform) 764 return( gIOPlatform->getModelName( name, maxLength )); 765 else 766 return( false ); 767} 768 769int PEGetPlatformEpoch(void) 770{ 771 if( gIOPlatform) 772 return( gIOPlatform->getBootROMType()); 773 else 774 return( -1 ); 775} 776 777int PEHaltRestart(unsigned int type) 778{ 779 IOPMrootDomain *pmRootDomain; 780 AbsoluteTime deadline; 781 thread_call_t shutdown_hang; 782 IORegistryEntry *node; 783 OSData *data; 784 uint32_t timeout = 30; 785 786 if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU) 787 { 788 pmRootDomain = IOService::getPMRootDomain(); 789 /* Notify IOKit PM clients of shutdown/restart 790 Clients subscribe to this message with a call to 791 IOService::registerInterest() 792 */ 793 794 /* Spawn a thread that will panic in 30 seconds. 795 If all goes well the machine will be off by the time 796 the timer expires. If the device wants a different 797 timeout, use that value instead of 30 seconds. 798 */ 799#define RESTART_NODE_PATH "/chosen" 800 node = IORegistryEntry::fromPath( RESTART_NODE_PATH, gIODTPlane ); 801 if ( node ) { 802 data = OSDynamicCast( OSData, node->getProperty( "halt-restart-timeout" ) ); 803 if ( data && data->getLength() == 4 ) 804 timeout = *((uint32_t *) data->getBytesNoCopy()); 805 } 806 807 shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut, 808 (thread_call_param_t)(uintptr_t) type); 809 clock_interval_to_deadline( timeout, kSecondScale, &deadline ); 810 thread_call_enter1_delayed( shutdown_hang, 0, deadline ); 811 812 pmRootDomain->handlePlatformHaltRestart(type); 813 /* This notification should have few clients who all do 814 their work synchronously. 815 816 In this "shutdown notification" context we don't give 817 drivers the option of working asynchronously and responding 818 later. PM internals make it very hard to wait for asynchronous 819 replies. 820 */ 821 } 822 823 if (gIOPlatform) return gIOPlatform->haltRestart(type); 824 else return -1; 825} 826 827UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length) 828{ 829 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length); 830 else return 0; 831} 832 833 834 835inline static int init_gIOOptionsEntry(void) 836{ 837 IORegistryEntry *entry; 838 void *nvram_entry; 839 volatile void **options; 840 int ret = -1; 841 842 if (gIOOptionsEntry) 843 return 0; 844 845 entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); 846 if (!entry) 847 return -1; 848 849 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry); 850 if (!nvram_entry) 851 goto release; 852 853 options = (volatile void **) &gIOOptionsEntry; 854 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) { 855 ret = 0; 856 goto release; 857 } 858 859 return 0; 860 861release: 862 entry->release(); 863 return ret; 864 865} 866 867/* pass in a NULL value if you just want to figure out the len */ 868boolean_t PEReadNVRAMProperty(const char *symbol, void *value, 869 unsigned int *len) 870{ 871 OSObject *obj; 872 OSData *data; 873 unsigned int vlen; 874 875 if (!symbol || !len) 876 goto err; 877 878 if (init_gIOOptionsEntry() < 0) 879 goto err; 880 881 vlen = *len; 882 *len = 0; 883 884 obj = gIOOptionsEntry->getProperty(symbol); 885 if (!obj) 886 goto err; 887 888 /* convert to data */ 889 data = OSDynamicCast(OSData, obj); 890 if (!data) 891 goto err; 892 893 *len = data->getLength(); 894 vlen = min(vlen, *len); 895 if (value && vlen) 896 memcpy((void *) value, data->getBytesNoCopy(), vlen); 897 898 return TRUE; 899 900err: 901 return FALSE; 902} 903 904 905boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value, 906 const unsigned int len) 907{ 908 const OSSymbol *sym; 909 OSData *data; 910 bool ret = false; 911 912 if (!symbol || !value || !len) 913 goto err; 914 915 if (init_gIOOptionsEntry() < 0) 916 goto err; 917 918 sym = OSSymbol::withCStringNoCopy(symbol); 919 if (!sym) 920 goto err; 921 922 data = OSData::withBytes((void *) value, len); 923 if (!data) 924 goto sym_done; 925 926 ret = gIOOptionsEntry->setProperty(sym, data); 927 data->release(); 928 929sym_done: 930 sym->release(); 931 932 if (ret == true) { 933 gIOOptionsEntry->sync(); 934 return TRUE; 935 } 936 937err: 938 return FALSE; 939} 940 941 942boolean_t PERemoveNVRAMProperty(const char *symbol) 943{ 944 const OSSymbol *sym; 945 946 if (!symbol) 947 goto err; 948 949 if (init_gIOOptionsEntry() < 0) 950 goto err; 951 952 sym = OSSymbol::withCStringNoCopy(symbol); 953 if (!sym) 954 goto err; 955 956 gIOOptionsEntry->removeProperty(sym); 957 958 sym->release(); 959 960 gIOOptionsEntry->sync(); 961 return TRUE; 962 963err: 964 return FALSE; 965 966} 967 968long PEGetGMTTimeOfDay(void) 969{ 970 clock_sec_t secs; 971 clock_usec_t usecs; 972 973 PEGetUTCTimeOfDay(&secs, &usecs); 974 return secs; 975} 976 977void PESetGMTTimeOfDay(long secs) 978{ 979 PESetUTCTimeOfDay(secs, 0); 980} 981 982void PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs) 983{ 984 clock_nsec_t nsecs = 0; 985 986 *secs = 0; 987 if (gIOPlatform) 988 gIOPlatform->getUTCTimeOfDay(secs, &nsecs); 989 990 assert(nsecs < NSEC_PER_SEC); 991 *usecs = nsecs / NSEC_PER_USEC; 992} 993 994void PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs) 995{ 996 assert(usecs < USEC_PER_SEC); 997 if (gIOPlatform) 998 gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC); 999} 1000 1001} /* extern "C" */ 1002 1003void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) 1004{ 1005 OSData * data; 1006 IORegistryEntry * entry; 1007 OSString * string = 0; 1008 uuid_string_t uuid; 1009 1010 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane ); 1011 if ( entry ) 1012 { 1013 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) ); 1014 if ( data && data->getLength( ) == 16 ) 1015 { 1016 SHA1_CTX context; 1017 uint8_t digest[ SHA_DIGEST_LENGTH ]; 1018 const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC }; 1019 1020 SHA1Init( &context ); 1021 SHA1Update( &context, space, sizeof( space ) ); 1022 SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) ); 1023 SHA1Final( digest, &context ); 1024 1025 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50; 1026 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80; 1027 1028 uuid_unparse( digest, uuid ); 1029 string = OSString::withCString( uuid ); 1030 } 1031 1032 entry->release( ); 1033 } 1034 1035 if ( string == 0 ) 1036 { 1037 entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); 1038 if ( entry ) 1039 { 1040 data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) ); 1041 if ( data && data->getLength( ) == sizeof( uuid_t ) ) 1042 { 1043 uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid ); 1044 string = OSString::withCString( uuid ); 1045 } 1046 1047 entry->release( ); 1048 } 1049 } 1050 1051 if ( string ) 1052 { 1053 getProvider( )->setProperty( kIOPlatformUUIDKey, string ); 1054 publishResource( kIOPlatformUUIDKey, string ); 1055 1056 string->release( ); 1057 } 1058 1059 publishResource("IONVRAM"); 1060} 1061 1062IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName, 1063 bool waitForFunction, 1064 void *param1, void *param2, 1065 void *param3, void *param4) 1066{ 1067 IOService *service, *_resources; 1068 1069 if (waitForFunction) { 1070 _resources = waitForService(resourceMatching(functionName)); 1071 } else { 1072 _resources = getResourceService(); 1073 } 1074 if (_resources == 0) return kIOReturnUnsupported; 1075 1076 service = OSDynamicCast(IOService, _resources->getProperty(functionName)); 1077 if (service == 0) return kIOReturnUnsupported; 1078 1079 return service->callPlatformFunction(functionName, waitForFunction, 1080 param1, param2, param3, param4); 1081} 1082 1083IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) 1084{ 1085 return 0; 1086} 1087 1088/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1089 1090#undef super 1091#define super IOPlatformExpert 1092 1093OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert ) 1094 1095OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0); 1096OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1); 1097OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2); 1098OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3); 1099OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4); 1100OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5); 1101OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6); 1102OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7); 1103 1104/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1105 1106IOService * IODTPlatformExpert::probe( IOService * provider, 1107 SInt32 * score ) 1108{ 1109 if( !super::probe( provider, score)) 1110 return( 0 ); 1111 1112 // check machine types 1113 if( !provider->compareNames( getProperty( gIONameMatchKey ) )) 1114 return( 0 ); 1115 1116 return( this); 1117} 1118 1119bool IODTPlatformExpert::configure( IOService * provider ) 1120{ 1121 if( !super::configure( provider)) 1122 return( false); 1123 1124 processTopLevel( provider ); 1125 1126 return( true ); 1127} 1128 1129IOService * IODTPlatformExpert::createNub( IORegistryEntry * from ) 1130{ 1131 IOService * nub; 1132 1133 nub = new IOPlatformDevice; 1134 if( nub) { 1135 if( !nub->init( from, gIODTPlane )) { 1136 nub->free(); 1137 nub = 0; 1138 } 1139 } 1140 return( nub); 1141} 1142 1143bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter ) 1144{ 1145 IORegistryEntry * next; 1146 IOService * nub; 1147 bool ok = true; 1148 1149 if( iter) { 1150 while( (next = (IORegistryEntry *) iter->getNextObject())) { 1151 1152 if( 0 == (nub = createNub( next ))) 1153 continue; 1154 1155 nub->attach( parent ); 1156 nub->registerService(); 1157 } 1158 iter->release(); 1159 } 1160 1161 return( ok ); 1162} 1163 1164void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry ) 1165{ 1166 OSIterator * kids; 1167 IORegistryEntry * next; 1168 IORegistryEntry * cpus; 1169 IORegistryEntry * options; 1170 1171 // infanticide 1172 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() ); 1173 if( kids) { 1174 while( (next = (IORegistryEntry *)kids->getNextObject())) { 1175 next->detachAll( gIODTPlane); 1176 } 1177 kids->release(); 1178 } 1179 1180 // Publish an IODTNVRAM class on /options. 1181 options = rootEntry->childFromPath("options", gIODTPlane); 1182 if (options) { 1183 dtNVRAM = new IODTNVRAM; 1184 if (dtNVRAM) { 1185 if (!dtNVRAM->init(options, gIODTPlane)) { 1186 dtNVRAM->release(); 1187 dtNVRAM = 0; 1188 } else { 1189 dtNVRAM->attach(this); 1190 dtNVRAM->registerService(); 1191 } 1192 } 1193 } 1194 1195 // Publish the cpus. 1196 cpus = rootEntry->childFromPath( "cpus", gIODTPlane); 1197 if ( cpus) 1198 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0)); 1199 1200 // publish top level, minus excludeList 1201 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList())); 1202} 1203 1204IOReturn IODTPlatformExpert::getNubResources( IOService * nub ) 1205{ 1206 if( nub->getDeviceMemory()) 1207 return( kIOReturnSuccess ); 1208 1209 IODTResolveAddressing( nub, "reg", 0); 1210 1211 return( kIOReturnSuccess); 1212} 1213 1214bool IODTPlatformExpert::compareNubName( const IOService * nub, 1215 OSString * name, OSString ** matched ) const 1216{ 1217 return( IODTCompareNubName( nub, name, matched ) 1218 || super::compareNubName( nub, name, matched) ); 1219} 1220 1221bool IODTPlatformExpert::getModelName( char * name, int maxLength ) 1222{ 1223 OSData * prop; 1224 const char * str; 1225 int len; 1226 char c; 1227 bool ok = false; 1228 1229 maxLength--; 1230 1231 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey ); 1232 if( prop ) { 1233 str = (const char *) prop->getBytesNoCopy(); 1234 1235 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) )) 1236 str += strlen( "AAPL," ); 1237 1238 len = 0; 1239 while( (c = *str++)) { 1240 if( (c == '/') || (c == ' ')) 1241 c = '-'; 1242 1243 name[ len++ ] = c; 1244 if( len >= maxLength) 1245 break; 1246 } 1247 1248 name[ len ] = 0; 1249 ok = true; 1250 } 1251 return( ok ); 1252} 1253 1254bool IODTPlatformExpert::getMachineName( char * name, int maxLength ) 1255{ 1256 OSData * prop; 1257 bool ok = false; 1258 1259 maxLength--; 1260 prop = (OSData *) getProvider()->getProperty( gIODTModelKey ); 1261 ok = (0 != prop); 1262 1263 if( ok ) 1264 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength ); 1265 1266 return( ok ); 1267} 1268 1269/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1270 1271void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram ) 1272{ 1273 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram); 1274 1275 super::registerNVRAMController(nvram); 1276} 1277 1278int IODTPlatformExpert::haltRestart(unsigned int type) 1279{ 1280 if (dtNVRAM) dtNVRAM->sync(); 1281 1282 return super::haltRestart(type); 1283} 1284 1285IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer, 1286 IOByteCount length) 1287{ 1288 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length); 1289 else return kIOReturnNotReady; 1290} 1291 1292IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer, 1293 IOByteCount length) 1294{ 1295 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length); 1296 else return kIOReturnNotReady; 1297} 1298 1299IOReturn IODTPlatformExpert::readNVRAMProperty( 1300 IORegistryEntry * entry, 1301 const OSSymbol ** name, OSData ** value ) 1302{ 1303 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value); 1304 else return kIOReturnNotReady; 1305} 1306 1307IOReturn IODTPlatformExpert::writeNVRAMProperty( 1308 IORegistryEntry * entry, 1309 const OSSymbol * name, OSData * value ) 1310{ 1311 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value); 1312 else return kIOReturnNotReady; 1313} 1314 1315OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void) 1316{ 1317 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions(); 1318 else return 0; 1319} 1320 1321IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID, 1322 IOByteCount offset, UInt8 * buffer, 1323 IOByteCount length) 1324{ 1325 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset, 1326 buffer, length); 1327 else return kIOReturnNotReady; 1328} 1329 1330IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID, 1331 IOByteCount offset, UInt8 * buffer, 1332 IOByteCount length) 1333{ 1334 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset, 1335 buffer, length); 1336 else return kIOReturnNotReady; 1337} 1338 1339IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) 1340{ 1341 IOByteCount lengthSaved = 0; 1342 1343 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length); 1344 1345 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length); 1346 1347 return lengthSaved; 1348} 1349 1350OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) { 1351 UInt8* serialNumber; 1352 unsigned int serialNumberSize; 1353 unsigned short pos = 0; 1354 char* temp; 1355 char SerialNo[30]; 1356 1357 if (myProperty != NULL) { 1358 serialNumberSize = myProperty->getLength(); 1359 serialNumber = (UInt8*)(myProperty->getBytesNoCopy()); 1360 temp = (char*)serialNumber; 1361 if (serialNumberSize > 0) { 1362 // check to see if this is a CTO serial number... 1363 while (pos < serialNumberSize && temp[pos] != '-') pos++; 1364 1365 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number 1366 memcpy(SerialNo, serialNumber + 12, 8); 1367 memcpy(&SerialNo[8], serialNumber, 3); 1368 SerialNo[11] = '-'; 1369 memcpy(&SerialNo[12], serialNumber + 3, 8); 1370 SerialNo[20] = 0; 1371 } else { // just a normal serial number 1372 memcpy(SerialNo, serialNumber + 13, 8); 1373 memcpy(&SerialNo[8], serialNumber, 3); 1374 SerialNo[11] = 0; 1375 } 1376 return OSString::withCString(SerialNo); 1377 } 1378 } 1379 return NULL; 1380} 1381 1382 1383/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1384 1385#undef super 1386#define super IOService 1387 1388OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService) 1389 1390OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0); 1391OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1); 1392OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2); 1393OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3); 1394 1395/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1396 1397bool IOPlatformExpertDevice::compareName( OSString * name, 1398 OSString ** matched ) const 1399{ 1400 return( IODTCompareNubName( this, name, matched )); 1401} 1402 1403bool 1404IOPlatformExpertDevice::initWithArgs( 1405 void * dtTop, void * p2, void * p3, void * p4 ) 1406{ 1407 IORegistryEntry * dt = 0; 1408 bool ok; 1409 1410 // dtTop may be zero on non- device tree systems 1411 if( dtTop && (dt = IODeviceTreeAlloc( dtTop ))) 1412 ok = super::init( dt, gIODTPlane ); 1413 else 1414 ok = super::init(); 1415 1416 if( !ok) 1417 return( false); 1418 1419 reserved = NULL; 1420 workLoop = IOWorkLoop::workLoop(); 1421 if (!workLoop) 1422 return false; 1423 1424 return( true); 1425} 1426 1427IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const 1428{ 1429 return workLoop; 1430} 1431 1432IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties ) 1433{ 1434 OSDictionary * dictionary; 1435 OSObject * object; 1436 IOReturn status; 1437 1438 status = super::setProperties( properties ); 1439 if ( status != kIOReturnUnsupported ) return status; 1440 1441 status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator ); 1442 if ( status != kIOReturnSuccess ) return status; 1443 1444 dictionary = OSDynamicCast( OSDictionary, properties ); 1445 if ( dictionary == 0 ) return kIOReturnBadArgument; 1446 1447 object = dictionary->getObject( kIOPlatformUUIDKey ); 1448 if ( object ) 1449 { 1450 IORegistryEntry * entry; 1451 OSString * string; 1452 uuid_t uuid; 1453 1454 string = ( OSString * ) getProperty( kIOPlatformUUIDKey ); 1455 if ( string ) return kIOReturnNotPermitted; 1456 1457 string = OSDynamicCast( OSString, object ); 1458 if ( string == 0 ) return kIOReturnBadArgument; 1459 1460 status = uuid_parse( string->getCStringNoCopy( ), uuid ); 1461 if ( status != 0 ) return kIOReturnBadArgument; 1462 1463 entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); 1464 if ( entry ) 1465 { 1466 entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) ); 1467 entry->release( ); 1468 } 1469 1470 setProperty( kIOPlatformUUIDKey, string ); 1471 publishResource( kIOPlatformUUIDKey, string ); 1472 1473 return kIOReturnSuccess; 1474 } 1475 1476 return kIOReturnUnsupported; 1477} 1478 1479void IOPlatformExpertDevice::free() 1480{ 1481 if (workLoop) 1482 workLoop->release(); 1483} 1484 1485/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1486 1487#undef super 1488#define super IOService 1489 1490OSDefineMetaClassAndStructors(IOPlatformDevice, IOService) 1491 1492OSMetaClassDefineReservedUnused(IOPlatformDevice, 0); 1493OSMetaClassDefineReservedUnused(IOPlatformDevice, 1); 1494OSMetaClassDefineReservedUnused(IOPlatformDevice, 2); 1495OSMetaClassDefineReservedUnused(IOPlatformDevice, 3); 1496 1497/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1498 1499bool IOPlatformDevice::compareName( OSString * name, 1500 OSString ** matched ) const 1501{ 1502 return( ((IOPlatformExpert *)getProvider())-> 1503 compareNubName( this, name, matched )); 1504} 1505 1506IOService * IOPlatformDevice::matchLocation( IOService * /* client */ ) 1507{ 1508 return( this ); 1509} 1510 1511IOReturn IOPlatformDevice::getResources( void ) 1512{ 1513 return( ((IOPlatformExpert *)getProvider())->getNubResources( this )); 1514} 1515 1516/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1517 1518/********************************************************************* 1519* IOPanicPlatform class 1520* 1521* If no legitimate IOPlatformDevice matches, this one does and panics 1522* the kernel with a suitable message. 1523*********************************************************************/ 1524 1525class IOPanicPlatform : IOPlatformExpert { 1526 OSDeclareDefaultStructors(IOPanicPlatform); 1527 1528public: 1529 bool start(IOService * provider); 1530}; 1531 1532 1533OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert); 1534 1535 1536bool IOPanicPlatform::start(IOService * provider) { 1537 const char * platform_name = "(unknown platform name)"; 1538 1539 if (provider) platform_name = provider->getName(); 1540 1541 panic("Unable to find driver for this platform: \"%s\".\n", 1542 platform_name); 1543 1544 return false; 1545} 1546 1547