The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOPlatformExpert.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: ec168f8c5a6be9a20a967bcd43892356


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.