|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * HISTORY ! 24: */ ! 25: ! 26: #include <IOKit/system.h> ! 27: ! 28: extern "C" { ! 29: #include <machine/machine_routines.h> ! 30: } ! 31: ! 32: #include <IOKit/IOInterrupts.h> ! 33: #include <IOKit/IOInterruptController.h> ! 34: #include <IOKit/IOPlatformExpert.h> ! 35: #include <IOKit/IOCPU.h> ! 36: #include <IOKit/IODeviceTreeSupport.h> ! 37: #include <IOKit/IORangeAllocator.h> ! 38: #include <libkern/c++/OSContainers.h> ! 39: #include <IOKit/IOLib.h> ! 40: #include <IOKit/nvram/IONVRAMController.h> ! 41: #include <IOKit/pwr_mgt/RootDomain.h> ! 42: #include <IOKit/IOKitDebug.h> ! 43: #include <IOKit/IOWorkLoop.h> ! 44: ! 45: #include <IOKit/assert.h> ! 46: ! 47: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 48: ! 49: #define super IOService ! 50: ! 51: OSDefineMetaClassAndStructors(IOPlatformExpert, IOService) ! 52: ! 53: static IOPlatformExpert * gIOPlatform; ! 54: ! 55: OSSymbol * gPlatformInterruptControllerName; ! 56: ! 57: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 58: ! 59: bool IOPlatformExpert::attach( IOService * provider ) ! 60: { ! 61: ! 62: if( !super::attach( provider )) ! 63: return( false); ! 64: ! 65: return( true); ! 66: } ! 67: ! 68: bool IOPlatformExpert::start( IOService * provider ) ! 69: { ! 70: IORangeAllocator * physicalRanges; ! 71: ! 72: if (!super::start(provider)) ! 73: return false; ! 74: ! 75: gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); ! 76: ! 77: physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, ! 78: IORangeAllocator::kLocking); ! 79: assert(physicalRanges); ! 80: setProperty("Platform Memory Ranges", physicalRanges); ! 81: ! 82: setPlatform( this ); ! 83: gIOPlatform = this; ! 84: ! 85: PMInstantiatePowerDomains(); ! 86: ! 87: return( configure(provider) ); ! 88: } ! 89: ! 90: bool IOPlatformExpert::configure( IOService * provider ) ! 91: { ! 92: OSSet * topLevel; ! 93: OSDictionary * dict; ! 94: IOService * nub; ! 95: ! 96: topLevel = OSDynamicCast( OSSet, getProperty("top-level")); ! 97: ! 98: if( topLevel) { ! 99: while( (dict = OSDynamicCast( OSDictionary, ! 100: topLevel->getAnyObject()))) { ! 101: dict->retain(); ! 102: topLevel->removeObject( dict ); ! 103: nub = createNub( dict ); ! 104: if( 0 == nub) ! 105: continue; ! 106: dict->release(); ! 107: nub->attach( this ); ! 108: nub->registerService(); ! 109: } ! 110: } ! 111: ! 112: return( true ); ! 113: } ! 114: ! 115: IOService * IOPlatformExpert::createNub( OSDictionary * from ) ! 116: { ! 117: IOService * nub; ! 118: ! 119: nub = new IOPlatformDevice; ! 120: if(nub) { ! 121: if( !nub->init( from )) { ! 122: nub->release(); ! 123: nub = 0; ! 124: } ! 125: } ! 126: return( nub); ! 127: } ! 128: ! 129: bool IOPlatformExpert::compareNubName( const IOService * nub, ! 130: OSString * name, OSString ** matched = 0 ) const ! 131: { ! 132: return( nub->IORegistryEntry::compareName( name, matched )); ! 133: } ! 134: ! 135: IOReturn IOPlatformExpert::getNubResources( IOService * nub ) ! 136: { ! 137: return( kIOReturnSuccess ); ! 138: } ! 139: ! 140: int IOPlatformExpert::getEpoch(void) ! 141: { ! 142: return _peEpoch; ! 143: } ! 144: ! 145: int IOPlatformExpert::getFamily(void) ! 146: { ! 147: return _peFamily; ! 148: } ! 149: ! 150: void IOPlatformExpert::setEpoch(int peEpoch) ! 151: { ! 152: _peEpoch = peEpoch; ! 153: } ! 154: ! 155: void IOPlatformExpert::setFamily(int peFamily) ! 156: { ! 157: _peFamily = peFamily; ! 158: } ! 159: ! 160: bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/) ! 161: { ! 162: return( false ); ! 163: } ! 164: ! 165: bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/) ! 166: { ! 167: return( false ); ! 168: } ! 169: ! 170: IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void) ! 171: { ! 172: return(OSDynamicCast(IORangeAllocator, ! 173: getProperty("Platform Memory Ranges"))); ! 174: } ! 175: ! 176: int (*PE_halt_restart)(unsigned int type) = 0; ! 177: ! 178: int IOPlatformExpert::haltRestart(unsigned int type) ! 179: { ! 180: ! 181: if (PE_halt_restart) return (*PE_halt_restart)(type); ! 182: else return -1; ! 183: } ! 184: ! 185: long IOPlatformExpert::getGMTTimeOfDay(void) ! 186: { ! 187: return(0); ! 188: } ! 189: ! 190: void IOPlatformExpert::setGMTTimeOfDay(long secs) ! 191: { ! 192: } ! 193: ! 194: ! 195: IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo ) ! 196: { ! 197: return( PE_current_console( consoleInfo)); ! 198: } ! 199: ! 200: IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo, ! 201: unsigned int op) ! 202: { ! 203: return( PE_initialize_console( consoleInfo, op )); ! 204: } ! 205: ! 206: void IOPlatformExpert::getDefaultBusSpeeds(int *numSpeeds, ! 207: unsigned long **speedList) ! 208: { ! 209: if (numSpeeds != 0) *numSpeeds = 0; ! 210: if (speedList != 0) *speedList = 0; ! 211: } ! 212: ! 213: IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController) ! 214: { ! 215: publishResource(name, interruptController); ! 216: ! 217: return kIOReturnSuccess; ! 218: } ! 219: ! 220: IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name) ! 221: { ! 222: IOInterruptController *interruptController; ! 223: IOService *service; ! 224: ! 225: service = waitForService(resourceMatching(name)); ! 226: ! 227: interruptController = OSDynamicCast(IOInterruptController, service->getProperty(name)); ! 228: ! 229: return interruptController; ! 230: } ! 231: ! 232: ! 233: void IOPlatformExpert::setCPUInterruptProperties(IOService *service) ! 234: { ! 235: IOCPUInterruptController *controller; ! 236: ! 237: controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController"))); ! 238: if (controller) controller->setCPUInterruptProperties(service); ! 239: } ! 240: ! 241: bool IOPlatformExpert::atInterruptLevel(void) ! 242: { ! 243: return ml_at_interrupt_context(); ! 244: } ! 245: ! 246: bool IOPlatformExpert::platformAdjustService(IOService */*service*/) ! 247: { ! 248: return true; ! 249: } ! 250: ! 251: ! 252: //********************************************************************************* ! 253: // PMLog ! 254: // ! 255: //********************************************************************************* ! 256: ! 257: void IOPlatformExpert::PMLog(const char * who,unsigned long event,unsigned long param1, unsigned long param2) ! 258: { ! 259: if( gIOKitDebug & kIOLogPower) ! 260: kprintf("%s %02d %08x %08x\n",who,event,param1,param2); ! 261: } ! 262: ! 263: ! 264: //********************************************************************************* ! 265: // PMInstantiatePowerDomains ! 266: // ! 267: // In this vanilla implementation, a Root Power Domain is instantiated. ! 268: // All other objects which register will be children of this Root. ! 269: // Where this is inappropriate, PMInstantiatePowerDomains is overridden ! 270: // in a platform-specific subclass. ! 271: //********************************************************************************* ! 272: ! 273: void IOPlatformExpert::PMInstantiatePowerDomains ( void ) ! 274: { ! 275: root = new IOPMrootDomain; ! 276: root->init(); ! 277: root->attach(this); ! 278: root->start(this); ! 279: root->youAreRoot(); ! 280: } ! 281: ! 282: ! 283: //********************************************************************************* ! 284: // PMRegisterDevice ! 285: // ! 286: // In this vanilla implementation, all callers are made children of the root power domain. ! 287: // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass. ! 288: //********************************************************************************* ! 289: ! 290: void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice) ! 291: { ! 292: root->addChild ( theDevice ); ! 293: } ! 294: ! 295: ! 296: /* ! 297: * Platform Expert handler for Non-volatile RAM. ! 298: Called by BSD driver. ! 299: Calls whatever NVRAM driver has registered. ! 300: That's either the IOPMUNVRAMController or the IOMapNVRAMController. ! 301: ! 302: Suurballe 11 Feb 1999 ! 303: */ ! 304: ! 305: ! 306: // global pointer to whichever NVRAM controller is present ! 307: IONVRAMController * gNVRAMController = 0; ! 308: ! 309: extern "C" { ! 310: ! 311: //int PEnvopen(dev_t dev, int flag, int devtype,struct proc * pp) ! 312: int PEnvopen(dev_t, int, int,struct proc * ) ! 313: { ! 314: if (gNVRAMController) return gNVRAMController->openNVRAM(); ! 315: else return kNoNVRAM; ! 316: } ! 317: ! 318: ! 319: //int PEnvclose(dev_t dev, int flag, int mode, struct proc * pp) ! 320: int PEnvclose(dev_t, int, int, struct proc *) ! 321: { ! 322: if (gNVRAMController) return gNVRAMController->closeNVRAM(); ! 323: else return kNoNVRAM; ! 324: } ! 325: ! 326: ! 327: int PEnvsync(void) ! 328: { ! 329: if (gNVRAMController) return gNVRAMController->syncNVRAM(); ! 330: else return kNoNVRAM; ! 331: } ! 332: ! 333: ! 334: int PEnvread(long offset, int length, unsigned char * where) ! 335: { ! 336: IOByteCount bytecount = length; ! 337: ! 338: if (gNVRAMController) ! 339: return gNVRAMController->readNVRAM(offset, &bytecount, where); ! 340: else return kNoNVRAM; ! 341: } ! 342: ! 343: ! 344: ! 345: int PEnvwrite(long offset, int length, unsigned char * where) ! 346: { ! 347: IOByteCount bytecount = length; ! 348: ! 349: if (gNVRAMController) ! 350: return gNVRAMController->writeNVRAM(offset, &bytecount, where); ! 351: else return kNoNVRAM; ! 352: } ! 353: ! 354: /* ! 355: * Callouts from BSD for machine name & model ! 356: */ ! 357: ! 358: boolean_t PEGetMachineName( char * name, int maxLength ) ! 359: { ! 360: if( gIOPlatform) ! 361: return( gIOPlatform->getMachineName( name, maxLength )); ! 362: else ! 363: return( false ); ! 364: } ! 365: ! 366: boolean_t PEGetModelName( char * name, int maxLength ) ! 367: { ! 368: if( gIOPlatform) ! 369: return( gIOPlatform->getModelName( name, maxLength )); ! 370: else ! 371: return( false ); ! 372: } ! 373: ! 374: int PEGetPlatformEpoch(void) ! 375: { ! 376: if( gIOPlatform) ! 377: return( gIOPlatform->getEpoch()); ! 378: else ! 379: return( -1 ); ! 380: } ! 381: ! 382: int PEHaltRestart(unsigned int type) ! 383: { ! 384: if (gNVRAMController) gNVRAMController->syncNVRAM(); ! 385: ! 386: if (gIOPlatform) return gIOPlatform->haltRestart(type); ! 387: else return -1; ! 388: } ! 389: ! 390: long PEGetGMTTimeOfDay(void) ! 391: { ! 392: if( gIOPlatform) ! 393: return( gIOPlatform->getGMTTimeOfDay()); ! 394: else ! 395: return( 0 ); ! 396: } ! 397: ! 398: void PESetGMTTimeOfDay(long secs) ! 399: { ! 400: if( gIOPlatform) ! 401: gIOPlatform->setGMTTimeOfDay(secs); ! 402: } ! 403: ! 404: } /* extern "C" */ ! 405: ! 406: void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) ! 407: { ! 408: gNVRAMController = caller; ! 409: ! 410: publishResource("IONVRAM"); ! 411: } ! 412: ! 413: ! 414: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 415: ! 416: #undef super ! 417: #define super IOPlatformExpert ! 418: ! 419: OSDefineMetaClass(IODTPlatformExpert, IOPlatformExpert) ! 420: OSDefineAbstractStructors( IODTPlatformExpert, IOPlatformExpert ) ! 421: ! 422: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 423: ! 424: IOService * IODTPlatformExpert::probe( IOService * provider, ! 425: SInt32 * score ) ! 426: { ! 427: if( !super::probe( provider, score)) ! 428: return( 0 ); ! 429: ! 430: // check machine types ! 431: if( !provider->compareNames( getProperty( gIONameMatchKey ) )) ! 432: return( 0 ); ! 433: ! 434: return( this); ! 435: } ! 436: ! 437: bool IODTPlatformExpert::configure( IOService * provider ) ! 438: { ! 439: if( !super::configure( provider)) ! 440: return( false); ! 441: ! 442: processTopLevel( provider ); ! 443: ! 444: return( true ); ! 445: } ! 446: ! 447: IOService * IODTPlatformExpert::createNub( IORegistryEntry * from ) ! 448: { ! 449: IOService * nub; ! 450: ! 451: nub = new IOPlatformDevice; ! 452: if( nub) { ! 453: if( !nub->init( from, gIODTPlane )) { ! 454: nub->free(); ! 455: nub = 0; ! 456: } ! 457: } ! 458: return( nub); ! 459: } ! 460: ! 461: bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter ) ! 462: { ! 463: IORegistryEntry * next; ! 464: IOService * nub; ! 465: bool ok = true; ! 466: ! 467: if( iter) { ! 468: while( (next = (IORegistryEntry *) iter->getNextObject())) { ! 469: ! 470: if( 0 == (nub = createNub( next ))) ! 471: continue; ! 472: ! 473: nub->attach( parent ); ! 474: nub->registerService(); ! 475: } ! 476: iter->release(); ! 477: } ! 478: ! 479: return( ok ); ! 480: } ! 481: ! 482: void IODTPlatformExpert::processTopLevel( IORegistryEntry * root ) ! 483: { ! 484: OSIterator * kids; ! 485: IORegistryEntry * next; ! 486: IORegistryEntry * cpus; ! 487: ! 488: // infanticide ! 489: kids = IODTFindMatchingEntries( root, 0, deleteList() ); ! 490: if( kids) { ! 491: while( (next = (IORegistryEntry *)kids->getNextObject())) { ! 492: next->detachAll( gIODTPlane); ! 493: } ! 494: kids->release(); ! 495: } ! 496: ! 497: // publish top level, minus excludeList ! 498: createNubs( this, IODTFindMatchingEntries( root, kIODTExclusive, excludeList())); ! 499: ! 500: cpus = root->childFromPath( "cpus", gIODTPlane); ! 501: // kids = IODTFindMatchingEntries( root, 0, "cpus"); ! 502: // cpus = (IORegistryEntry *)kids->getNextObject(); ! 503: if ( cpus) ! 504: // publish cpus/* ! 505: createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0)); ! 506: ! 507: } ! 508: ! 509: IOReturn IODTPlatformExpert::getNubResources( IOService * nub ) ! 510: { ! 511: if( nub->getDeviceMemory()) ! 512: return( kIOReturnSuccess ); ! 513: ! 514: IODTResolveAddressing( nub, "reg", 0); ! 515: ! 516: return( kIOReturnSuccess); ! 517: } ! 518: ! 519: bool IODTPlatformExpert::compareNubName( const IOService * nub, ! 520: OSString * name, OSString ** matched ) const ! 521: { ! 522: return( IODTCompareNubName( nub, name, matched ) ! 523: || super::compareNubName( nub, name, matched) ); ! 524: } ! 525: ! 526: bool IODTPlatformExpert::getModelName( char * name, int maxLength ) ! 527: { ! 528: OSData * prop; ! 529: const char * str; ! 530: int len; ! 531: char c; ! 532: bool ok = false; ! 533: ! 534: maxLength--; ! 535: ! 536: prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey ); ! 537: if( prop ) { ! 538: str = (const char *) prop->getBytesNoCopy(); ! 539: ! 540: if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) )) ! 541: str += strlen( "AAPL," ); ! 542: ! 543: len = 0; ! 544: while( (c = *str++)) { ! 545: if( (c == '/') || (c == ' ')) ! 546: c = '-'; ! 547: ! 548: name[ len++ ] = c; ! 549: if( len >= maxLength) ! 550: break; ! 551: } ! 552: ! 553: name[ len ] = 0; ! 554: ok = true; ! 555: } ! 556: return( ok ); ! 557: } ! 558: ! 559: bool IODTPlatformExpert::getMachineName( char * name, int maxLength ) ! 560: { ! 561: OSData * prop; ! 562: bool ok = false; ! 563: ! 564: maxLength--; ! 565: prop = (OSData *) getProvider()->getProperty( gIODTModelKey ); ! 566: ok = (0 != prop); ! 567: ! 568: if( ok ) ! 569: strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength ); ! 570: ! 571: return( ok ); ! 572: } ! 573: ! 574: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 575: ! 576: enum { ! 577: kMaxNVNameLen = 4, ! 578: kMaxNVDataLen = 8 ! 579: }; ! 580: ! 581: #pragma options align=mac68k ! 582: struct NVRAMProperty ! 583: { ! 584: IONVRAMDescriptor header; ! 585: UInt8 nameLen; ! 586: UInt8 name[ kMaxNVNameLen ]; ! 587: UInt8 dataLen; ! 588: UInt8 data[ kMaxNVDataLen ]; ! 589: }; ! 590: #pragma options align=reset ! 591: ! 592: ! 593: void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram ) ! 594: { ! 595: UInt32 off; ! 596: IOReturn err; ! 597: IOByteCount len; ! 598: ! 599: err = getNVRAMPartitionOffset( kIONameRegistryNVRAMPartition, &off ); ! 600: ! 601: if( kIOReturnSuccess == err) { ! 602: ! 603: if( 0 == nvramBuffer) ! 604: nvramBuffer = IONew( UInt8, kIONameRegistryNVRAMPartitionSize ); ! 605: assert( nvramBuffer ); ! 606: ! 607: err = nvram->openNVRAM(); ! 608: if( kIOReturnSuccess == err) { ! 609: len = kIONameRegistryNVRAMPartitionSize; ! 610: err = nvram->readNVRAM( off, &len, nvramBuffer ); ! 611: nvram->closeNVRAM(); ! 612: } ! 613: ! 614: if( err) ! 615: bzero( nvramBuffer, kIONameRegistryNVRAMPartitionSize ); ! 616: } ! 617: ! 618: super::registerNVRAMController( nvram ); ! 619: } ! 620: ! 621: bool IODTPlatformExpert::searchNVRAMProperty( IONVRAMDescriptor * hdr, ! 622: UInt32 * where ) ! 623: { ! 624: UInt32 off; ! 625: SInt32 nvEnd; ! 626: ! 627: getNVRAMPartitionOffset( kIONameRegistryNVRAMPartition, &off ); ! 628: ! 629: nvEnd = *((UInt16 *) nvramBuffer); ! 630: if( getEpoch()) ! 631: nvEnd -= 0x100; // on new world, offset to partition start ! 632: else ! 633: nvEnd -= off; // on old world, absolute ! 634: if( (nvEnd < 0) || (nvEnd >= kIONameRegistryNVRAMPartitionSize) ) ! 635: nvEnd = 2; ! 636: ! 637: off = 2; ! 638: while( (off + sizeof( NVRAMProperty)) <= (UInt32) nvEnd) { ! 639: ! 640: if( 0 == bcmp( nvramBuffer + off, hdr, sizeof( *hdr))) { ! 641: *where = off; ! 642: return( true ); ! 643: } ! 644: off += sizeof( NVRAMProperty); ! 645: } ! 646: ! 647: if( (nvEnd + sizeof( NVRAMProperty)) <= kIONameRegistryNVRAMPartitionSize) ! 648: *where = nvEnd; ! 649: else ! 650: *where = 0; ! 651: ! 652: return( false ); ! 653: } ! 654: ! 655: IOReturn IODTPlatformExpert::readNVRAMPropertyType0( ! 656: IORegistryEntry * entry, ! 657: const OSSymbol ** name, OSData ** value ) ! 658: { ! 659: IONVRAMDescriptor hdr; ! 660: NVRAMProperty * prop; ! 661: IOByteCount len; ! 662: UInt32 off; ! 663: IOReturn err; ! 664: char nameBuf[ kMaxNVNameLen + 1 ]; ! 665: ! 666: if( !nvramBuffer) ! 667: return( kIOReturnUnsupported ); ! 668: if( !entry || !name || !value) ! 669: return( kIOReturnBadArgument ); ! 670: ! 671: if( kIOReturnSuccess != (err = IODTMakeNVDescriptor( entry, &hdr))) ! 672: return( err); ! 673: ! 674: if( searchNVRAMProperty( &hdr, &off)) { ! 675: ! 676: prop = (NVRAMProperty *) (nvramBuffer + off); ! 677: ! 678: len = prop->nameLen; ! 679: if( len > kMaxNVNameLen) ! 680: len = kMaxNVNameLen; ! 681: strncpy( nameBuf, (const char *) prop->name, len ); ! 682: nameBuf[ len ] = 0; ! 683: *name = OSSymbol::withCString( nameBuf ); ! 684: ! 685: len = prop->dataLen; ! 686: if( len > kMaxNVDataLen) ! 687: len = kMaxNVDataLen; ! 688: *value = OSData::withBytes( prop->data, len ); ! 689: ! 690: if( *name && *value ) ! 691: return( kIOReturnSuccess ); ! 692: else ! 693: return( kIOReturnNoMemory ); ! 694: } ! 695: ! 696: return( kIOReturnNoResources ); ! 697: } ! 698: ! 699: IOReturn IODTPlatformExpert::writeNVRAMPropertyType0( ! 700: IORegistryEntry * entry, ! 701: const OSSymbol * name, OSData * value ) ! 702: { ! 703: IONVRAMDescriptor hdr; ! 704: NVRAMProperty * prop; ! 705: IOByteCount len; ! 706: IOByteCount nameLen; ! 707: IOByteCount dataLen; ! 708: UInt32 off; ! 709: IOReturn err; ! 710: UInt32 start; ! 711: UInt16 nvLen; ! 712: bool exists; ! 713: ! 714: if( !nvramBuffer) ! 715: return( kIOReturnUnsupported ); ! 716: if( !entry || !name || !value) ! 717: return( kIOReturnBadArgument ); ! 718: ! 719: nameLen = name->getLength(); ! 720: dataLen = value->getLength(); ! 721: if( nameLen > kMaxNVNameLen) ! 722: return( kIOReturnNoSpace); ! 723: if( dataLen > kMaxNVDataLen) ! 724: return( kIOReturnNoSpace); ! 725: ! 726: if( kIOReturnSuccess != (err = IODTMakeNVDescriptor( entry, &hdr))) ! 727: return( err); ! 728: ! 729: exists = searchNVRAMProperty( &hdr, &off); ! 730: if( !off) ! 731: return( kIOReturnNoMemory); ! 732: ! 733: prop = (NVRAMProperty *) (nvramBuffer + off); ! 734: if( !exists) ! 735: bcopy( &hdr, &prop->header, sizeof( hdr)); ! 736: ! 737: prop->nameLen = nameLen; ! 738: bcopy( name->getCStringNoCopy(), prop->name, nameLen ); ! 739: prop->dataLen = dataLen; ! 740: bcopy( value->getBytesNoCopy(), prop->data, dataLen ); ! 741: ! 742: getNVRAMPartitionOffset( kIONameRegistryNVRAMPartition, &start ); ! 743: if( !exists) { ! 744: nvLen = off + sizeof( NVRAMProperty); ! 745: if( getEpoch()) ! 746: nvLen += 0x100; ! 747: else ! 748: nvLen += start; ! 749: *((UInt16 *) nvramBuffer) = nvLen; ! 750: } ! 751: ! 752: err = gNVRAMController->openNVRAM(); ! 753: if( kIOReturnSuccess == err) { ! 754: len = 2; ! 755: if( !exists) ! 756: err = gNVRAMController->writeNVRAM( start, &len, nvramBuffer ); ! 757: if( kIOReturnSuccess == err) { ! 758: len = sizeof( NVRAMProperty); ! 759: err = gNVRAMController->writeNVRAM( start + off, &len, ! 760: nvramBuffer + off ); ! 761: } ! 762: gNVRAMController->closeNVRAM(); ! 763: } ! 764: ! 765: return( err ); ! 766: } ! 767: ! 768: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 769: ! 770: OSData * IODTPlatformExpert::getType1NVRAM( void ) ! 771: { ! 772: OSData * data; ! 773: IORegistryEntry * options; ! 774: ! 775: options = IORegistryEntry::fromPath( "/options", gIODTPlane); ! 776: if( !options) ! 777: return( 0 ); ! 778: ! 779: data = OSDynamicCast( OSData, options->getProperty( "aapl,pci" )); ! 780: if( data && (0 == data->getLength())) ! 781: data = 0; ! 782: ! 783: return( data ); ! 784: } ! 785: ! 786: OSData * IODTPlatformExpert::unescapeValueToBinary( UInt8 * value ) ! 787: { ! 788: OSData * data = 0; ! 789: UInt8 * buffer; ! 790: UInt32 len, totalLen = 0; ! 791: UInt8 byte; ! 792: enum { kMaxValueSize = 256 }; ! 793: ! 794: buffer = IONew( UInt8, kMaxValueSize ); ! 795: if( !buffer) ! 796: return( 0 ); ! 797: ! 798: while( 0 != (byte = *(value++))) { ! 799: ! 800: if( 0xff == byte) { ! 801: byte = *(value++); ! 802: len = byte & 0x7f; ! 803: byte = (byte & 0x80) ? 0xff : 0; ! 804: } else ! 805: len = 1; ! 806: ! 807: if( (totalLen + len) >= kMaxValueSize) { ! 808: totalLen = 0; ! 809: break; ! 810: } ! 811: ! 812: memset( (void *) (buffer + totalLen), byte, len ); ! 813: totalLen += len; ! 814: } ! 815: ! 816: if( totalLen) ! 817: data = OSData::withBytes( buffer, totalLen ); ! 818: ! 819: IODelete( buffer, UInt8, kMaxValueSize ); ! 820: ! 821: return( data ); ! 822: } ! 823: ! 824: IOReturn IODTPlatformExpert::readNVRAMPropertyType1( ! 825: IORegistryEntry * entry, ! 826: const OSSymbol ** name, OSData ** value ) ! 827: { ! 828: IOReturn err = kIOReturnNoResources; ! 829: OSData * data; ! 830: UInt8 * start; ! 831: UInt8 * end; ! 832: UInt8 * where; ! 833: UInt8 * nvPath = 0; ! 834: UInt8 * nvName = 0; ! 835: UInt8 byte; ! 836: ! 837: if( 0 == (data = getType1NVRAM())) ! 838: return( kIOReturnUnsupported ); ! 839: ! 840: // data must have length from getType1NVRAM() ! 841: start = (UInt8 *) data->getBytesNoCopy(); ! 842: if( strlen( (const char *) start) == (data->getLength() - 1)) { ! 843: data = unescapeValueToBinary( start ); ! 844: if( 0 == data) ! 845: return( kIOReturnUnsupported ); ! 846: } else ! 847: data->retain(); ! 848: ! 849: start = (UInt8 *) data->getBytesNoCopy(); ! 850: end = start + data->getLength(); ! 851: ! 852: where = start; ! 853: while( where < end) { ! 854: ! 855: byte = *(where++); ! 856: if( byte) ! 857: continue; ! 858: ! 859: if( !nvPath) ! 860: nvPath = start; ! 861: else if( !nvName) ! 862: nvName = start; ! 863: ! 864: else if( entry == IORegistryEntry::fromPath( (const char *) nvPath, gIODTPlane )) { ! 865: ! 866: *name = OSSymbol::withCString( (const char *) nvName ); ! 867: *value = unescapeValueToBinary( start ); ! 868: if( *name && *value ) ! 869: err = kIOReturnSuccess; ! 870: else ! 871: err = kIOReturnNoMemory; ! 872: break; ! 873: ! 874: } else ! 875: nvPath = nvName = 0; ! 876: ! 877: start = where; ! 878: } ! 879: data->release(); ! 880: ! 881: return( err ); ! 882: } ! 883: ! 884: IOReturn IODTPlatformExpert::writeNVRAMPropertyType1( ! 885: IORegistryEntry * entry, ! 886: const OSSymbol * name, OSData * value ) ! 887: { ! 888: OSData * data; ! 889: ! 890: if( 0 == (data = getType1NVRAM())) ! 891: return( kIOReturnUnsupported ); ! 892: ! 893: // tidbit left for PR2 ! 894: return( kIOReturnNoResources ); ! 895: } ! 896: ! 897: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 898: ! 899: ! 900: IOReturn IODTPlatformExpert::readNVRAMProperty( ! 901: IORegistryEntry * entry, ! 902: const OSSymbol ** name, OSData ** value ) ! 903: { ! 904: IOReturn err; ! 905: ! 906: err = readNVRAMPropertyType1( entry, name, value ); ! 907: ! 908: if( kIOReturnUnsupported == err) ! 909: err = readNVRAMPropertyType0( entry, name, value ); ! 910: ! 911: return( err ); ! 912: } ! 913: ! 914: IOReturn IODTPlatformExpert::writeNVRAMProperty( ! 915: IORegistryEntry * entry, ! 916: const OSSymbol * name, OSData * value ) ! 917: { ! 918: IOReturn err; ! 919: ! 920: err = writeNVRAMPropertyType1( entry, name, value ); ! 921: ! 922: if( kIOReturnUnsupported == err) ! 923: err = writeNVRAMPropertyType0( entry, name, value ); ! 924: ! 925: return( err ); ! 926: } ! 927: ! 928: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 929: ! 930: #undef super ! 931: #define super IOService ! 932: ! 933: OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService) ! 934: ! 935: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 936: ! 937: bool IOPlatformExpertDevice::compareName( OSString * name, ! 938: OSString ** matched = 0 ) const ! 939: { ! 940: return( IODTCompareNubName( this, name, matched )); ! 941: } ! 942: ! 943: bool ! 944: IOPlatformExpertDevice::initWithArgs( ! 945: void * dtTop, void * p2, void * p3, void * p4 ) ! 946: { ! 947: IORegistryEntry * dt = 0; ! 948: void * argsData[ 4 ]; ! 949: bool ok; ! 950: ! 951: // dtTop may be zero on non- device tree systems ! 952: if( dtTop && (dt = IODeviceTreeAlloc( dtTop ))) ! 953: ok = super::init( dt, gIODTPlane ); ! 954: else ! 955: ok = super::init(); ! 956: ! 957: if( !ok) ! 958: return( false); ! 959: ! 960: workLoop = IOWorkLoop::workLoop(); ! 961: if (!workLoop) ! 962: return false; ! 963: ! 964: argsData[ 0 ] = dtTop; ! 965: argsData[ 1 ] = p2; ! 966: argsData[ 2 ] = p3; ! 967: argsData[ 3 ] = p4; ! 968: ! 969: setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData)); ! 970: ! 971: return( true); ! 972: } ! 973: ! 974: IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const ! 975: { ! 976: return workLoop; ! 977: } ! 978: ! 979: void IOPlatformExpertDevice::free() ! 980: { ! 981: if (workLoop) ! 982: workLoop->release(); ! 983: } ! 984: ! 985: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 986: ! 987: #undef super ! 988: #define super IOService ! 989: ! 990: OSDefineMetaClassAndStructors(IOPlatformDevice, IOService) ! 991: ! 992: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 993: ! 994: bool IOPlatformDevice::compareName( OSString * name, ! 995: OSString ** matched = 0 ) const ! 996: { ! 997: return( ((IOPlatformExpert *)getProvider())-> ! 998: compareNubName( this, name, matched )); ! 999: } ! 1000: ! 1001: IOService * IOPlatformDevice::matchLocation( IOService * /* client */ ) ! 1002: { ! 1003: return( this ); ! 1004: } ! 1005: ! 1006: IOReturn IOPlatformDevice::getResources( void ) ! 1007: { ! 1008: return( ((IOPlatformExpert *)getProvider())->getNubResources( this )); ! 1009: } ! 1010: ! 1011: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.