Annotation of XNU/iokit/Kernel/IOPlatformExpert.cpp, revision 1.1.1.1

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: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.