X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/99c3a10404e5d1ef94397ab4df5a8b74711fc4d3..c6bf4f310a33a9262d455ea4d3f0630b1255e3fe:/iokit/Kernel/IOPlatformExpert.cpp diff --git a/iokit/Kernel/IOPlatformExpert.cpp b/iokit/Kernel/IOPlatformExpert.cpp index e7f393474..1fb74c642 100644 --- a/iokit/Kernel/IOPlatformExpert.cpp +++ b/iokit/Kernel/IOPlatformExpert.cpp @@ -1,8 +1,8 @@ /* - * Copyright (c) 1998-2010 Apple Inc. All rights reserved. + * Copyright (c) 1998-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,10 +22,10 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ - + #include #include #include @@ -39,8 +39,11 @@ #include #include #include +#include +#include #include +#include #include #include @@ -52,26 +55,45 @@ extern "C" { #include } -void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg); +#define kShutdownTimeout 30 //in secs + +#if defined(XNU_TARGET_OS_OSX) + +boolean_t coprocessor_cross_panic_enabled = TRUE; +#define APPLE_VENDOR_VARIABLE_GUID "4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14" +#endif /* defined(XNU_TARGET_OS_OSX) */ + +void printDictionaryKeys(OSDictionary * inDictionary, char * inMsg); static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen); +/* + * There are drivers which take mutexes in the quiesce callout or pass + * the quiesce/active action to super. Even though it sometimes panics, + * because it doesn't *always* panic, they get away with it. + * We need a chicken bit to diagnose and fix them all before this + * can be enabled by default. + * + * tracks turning this on by default. + */ +uint32_t gEnforceQuiesceSafety = 0; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super IOService OSDefineMetaClassAndStructors(IOPlatformExpert, IOService) -OSMetaClassDefineReservedUsed(IOPlatformExpert, 0); - -OSMetaClassDefineReservedUsed(IOPlatformExpert, 1); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 2); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 3); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 4); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 5); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 6); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 7); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 8); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 9); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 0); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 1); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 2); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 3); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 4); + +OSMetaClassDefineReservedUnused(IOPlatformExpert, 5); +OSMetaClassDefineReservedUnused(IOPlatformExpert, 6); +OSMetaClassDefineReservedUnused(IOPlatformExpert, 7); +OSMetaClassDefineReservedUnused(IOPlatformExpert, 8); +OSMetaClassDefineReservedUnused(IOPlatformExpert, 9); OSMetaClassDefineReservedUnused(IOPlatformExpert, 10); OSMetaClassDefineReservedUnused(IOPlatformExpert, 11); @@ -84,283 +106,370 @@ OSSymbol * gPlatformInterruptControllerName; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -bool IOPlatformExpert::attach( IOService * provider ) -{ - - if( !super::attach( provider )) - return( false); - - return( true); -} - -bool IOPlatformExpert::start( IOService * provider ) -{ - IORangeAllocator * physicalRanges; - OSData * busFrequency; - uint32_t debugFlags; - - if (!super::start(provider)) - return false; - - // Override the mapper present flag is requested by boot arguments. - if (PE_parse_boot_argn("dart", &debugFlags, sizeof (debugFlags)) && (debugFlags == 0)) - removeProperty(kIOPlatformMapperPresentKey); - if (PE_parse_boot_argn("-x", &debugFlags, sizeof (debugFlags))) - removeProperty(kIOPlatformMapperPresentKey); +bool +IOPlatformExpert::attach( IOService * provider ) +{ + if (!super::attach( provider )) { + return false; + } - // Register the presence or lack thereof a system - // PCI address mapper with the IOMapper class - IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey)); - - gIOInterruptControllers = OSDictionary::withCapacity(1); - gIOInterruptControllersLock = IOLockAlloc(); - - // Correct the bus frequency in the device tree. - busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4); - provider->setProperty("clock-frequency", busFrequency); - busFrequency->release(); - - gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); - - physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, - IORangeAllocator::kLocking); - assert(physicalRanges); - setProperty("Platform Memory Ranges", physicalRanges); - - setPlatform( this ); - gIOPlatform = this; - - PMInstantiatePowerDomains(); - - // Parse the serial-number data and publish a user-readable string - OSData* mydata = (OSData*) (provider->getProperty("serial-number")); - if (mydata != NULL) { - OSString *serNoString = createSystemSerialNumberString(mydata); - if (serNoString != NULL) { - provider->setProperty(kIOPlatformSerialNumberKey, serNoString); - serNoString->release(); - } - } - - return( configure(provider) ); + return true; } -bool IOPlatformExpert::configure( IOService * provider ) +bool +IOPlatformExpert::start( IOService * provider ) { - OSSet * topLevel; - OSDictionary * dict; - IOService * nub; + IORangeAllocator * physicalRanges; + OSData * busFrequency; + uint32_t debugFlags; + - topLevel = OSDynamicCast( OSSet, getProperty("top-level")); + if (!super::start(provider)) { + return false; + } + + // Override the mapper present flag is requested by boot arguments, if SIP disabled. +#if CONFIG_CSR + if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) == 0) +#endif /* CONFIG_CSR */ + { + if (PE_parse_boot_argn("dart", &debugFlags, sizeof(debugFlags)) && (debugFlags == 0)) { + removeProperty(kIOPlatformMapperPresentKey); + } +#if DEBUG || DEVELOPMENT + if (PE_parse_boot_argn("-x", &debugFlags, sizeof(debugFlags))) { + removeProperty(kIOPlatformMapperPresentKey); + } +#endif /* DEBUG || DEVELOPMENT */ + } - if( topLevel) { - while( (dict = OSDynamicCast( OSDictionary, - topLevel->getAnyObject()))) { - dict->retain(); - topLevel->removeObject( dict ); - nub = createNub( dict ); - if( 0 == nub) - continue; - dict->release(); - nub->attach( this ); - nub->registerService(); - } - } + // Register the presence or lack thereof a system + // PCI address mapper with the IOMapper class + IOMapper::setMapperRequired(NULL != getProperty(kIOPlatformMapperPresentKey)); - return( true ); + gIOInterruptControllers = OSDictionary::withCapacity(1); + gIOInterruptControllersLock = IOLockAlloc(); + + // Correct the bus frequency in the device tree. + busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4); + provider->setProperty("clock-frequency", busFrequency); + busFrequency->release(); + + gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); + + physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, + IORangeAllocator::kLocking); + assert(physicalRanges); + setProperty("Platform Memory Ranges", physicalRanges); + + setPlatform( this ); + gIOPlatform = this; + + PMInstantiatePowerDomains(); + + // Parse the serial-number data and publish a user-readable string + OSData* mydata = (OSData*) (provider->getProperty("serial-number")); + if (mydata != NULL) { + OSString *serNoString = createSystemSerialNumberString(mydata); + if (serNoString != NULL) { + provider->setProperty(kIOPlatformSerialNumberKey, serNoString); + serNoString->release(); + } + } + +#if !CONFIG_EMBEDDED + if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) { + coprocessor_paniclog_flush = TRUE; + extended_debug_log_init(); + } +#endif + + PE_parse_boot_argn("enforce_quiesce_safety", &gEnforceQuiesceSafety, + sizeof(gEnforceQuiesceSafety)); + + return configure(provider); } -IOService * IOPlatformExpert::createNub( OSDictionary * from ) +bool +IOPlatformExpert::configure( IOService * provider ) +{ + OSSet * topLevel; + OSDictionary * dict; + IOService * nub; + + topLevel = OSDynamicCast( OSSet, getProperty("top-level")); + + if (topLevel) { + while ((dict = OSDynamicCast( OSDictionary, + topLevel->getAnyObject()))) { + dict->retain(); + topLevel->removeObject( dict ); + nub = createNub( dict ); + if (NULL == nub) { + continue; + } + dict->release(); + nub->attach( this ); + nub->registerService(); + } + } + + return true; +} + +IOService * +IOPlatformExpert::createNub( OSDictionary * from ) { - IOService * nub; + IOService * nub; - nub = new IOPlatformDevice; - if(nub) { - if( !nub->init( from )) { - nub->release(); - nub = 0; + nub = new IOPlatformDevice; + if (nub) { + if (!nub->init( from )) { + nub->release(); + nub = NULL; + } } - } - return( nub); + return nub; } -bool IOPlatformExpert::compareNubName( const IOService * nub, - OSString * name, OSString ** matched ) const +bool +IOPlatformExpert::compareNubName( const IOService * nub, + OSString * name, OSString ** matched ) const { - return( nub->IORegistryEntry::compareName( name, matched )); + return nub->IORegistryEntry::compareName( name, matched ); } -IOReturn IOPlatformExpert::getNubResources( IOService * nub ) +IOReturn +IOPlatformExpert::getNubResources( IOService * nub ) { - return( kIOReturnSuccess ); + return kIOReturnSuccess; } -long IOPlatformExpert::getBootROMType(void) +long +IOPlatformExpert::getBootROMType(void) { - return _peBootROMType; + return _peBootROMType; } -long IOPlatformExpert::getChipSetType(void) +long +IOPlatformExpert::getChipSetType(void) { - return _peChipSetType; + return _peChipSetType; } -long IOPlatformExpert::getMachineType(void) +long +IOPlatformExpert::getMachineType(void) { - return _peMachineType; + return _peMachineType; } -void IOPlatformExpert::setBootROMType(long peBootROMType) +void +IOPlatformExpert::setBootROMType(long peBootROMType) { - _peBootROMType = peBootROMType; + _peBootROMType = peBootROMType; } -void IOPlatformExpert::setChipSetType(long peChipSetType) +void +IOPlatformExpert::setChipSetType(long peChipSetType) { - _peChipSetType = peChipSetType; + _peChipSetType = peChipSetType; } -void IOPlatformExpert::setMachineType(long peMachineType) +void +IOPlatformExpert::setMachineType(long peMachineType) { - _peMachineType = peMachineType; + _peMachineType = peMachineType; } -bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/) +bool +IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/) { - return( false ); + return false; } -bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/) +bool +IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/) { - return( false ); + return false; } -OSString* IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty) +OSString* +IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty) { - return NULL; + return NULL; } -IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void) +IORangeAllocator * +IOPlatformExpert::getPhysicalRangeAllocator(void) { - return(OSDynamicCast(IORangeAllocator, - getProperty("Platform Memory Ranges"))); + return OSDynamicCast(IORangeAllocator, + getProperty("Platform Memory Ranges")); } -int (*PE_halt_restart)(unsigned int type) = 0; +int (*PE_halt_restart)(unsigned int type) = NULL; -int IOPlatformExpert::haltRestart(unsigned int type) +int +IOPlatformExpert::haltRestart(unsigned int type) { - if (type == kPEPanicSync) return 0; + if (type == kPEPanicSync) { + return 0; + } - if (type == kPEHangCPU) while (true) {} + if (type == kPEHangCPU) { + while (true) { + } + } - if (type == kPEUPSDelayHaltCPU) { - // RestartOnPowerLoss feature was turned on, proceed with shutdown. - type = kPEHaltCPU; - } + if (type == kPEUPSDelayHaltCPU) { + // RestartOnPowerLoss feature was turned on, proceed with shutdown. + type = kPEHaltCPU; + } - // On ARM kPEPanicRestartCPU is supported in the drivers - if (type == kPEPanicRestartCPU) - type = kPERestartCPU; +#if !CONFIG_EMBEDDED + // On ARM kPEPanicRestartCPU is supported in the drivers + if (type == kPEPanicRestartCPU) { + type = kPERestartCPU; + } +#endif - if (PE_halt_restart) return (*PE_halt_restart)(type); - else return -1; + if (PE_halt_restart) { + return (*PE_halt_restart)(type); + } else { + return -1; + } } -void IOPlatformExpert::sleepKernel(void) +void +IOPlatformExpert::sleepKernel(void) { #if 0 - long cnt; - boolean_t intState; - - intState = ml_set_interrupts_enabled(false); - - for (cnt = 0; cnt < 10000; cnt++) { - IODelay(1000); - } - - ml_set_interrupts_enabled(intState); + long cnt; + boolean_t intState; + + intState = ml_set_interrupts_enabled(false); + + for (cnt = 0; cnt < 10000; cnt++) { + IODelay(1000); + } + + ml_set_interrupts_enabled(intState); #else // PE_initialize_console(0, kPEDisableScreen); - - IOCPUSleepKernel(); - + + IOCPUSleepKernel(); + // PE_initialize_console(0, kPEEnableScreen); #endif } -long IOPlatformExpert::getGMTTimeOfDay(void) +long +IOPlatformExpert::getGMTTimeOfDay(void) { - return(0); + return 0; } -void IOPlatformExpert::setGMTTimeOfDay(long secs) +void +IOPlatformExpert::setGMTTimeOfDay(long secs) { } -IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo ) +IOReturn +IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo ) +{ + return PE_current_console( consoleInfo); +} + +IOReturn +IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo, + unsigned int op) +{ + return PE_initialize_console( consoleInfo, op ); +} + +IOReturn +IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController) { - return( PE_current_console( consoleInfo)); + IOLockLock(gIOInterruptControllersLock); + + gIOInterruptControllers->setObject(name, interruptController); + + IOLockWakeup(gIOInterruptControllersLock, + gIOInterruptControllers, /* one-thread */ false); + + IOLockUnlock(gIOInterruptControllersLock); + + return kIOReturnSuccess; } -IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo, - unsigned int op) +IOReturn +IOPlatformExpert::deregisterInterruptController(OSSymbol *name) { - return( PE_initialize_console( consoleInfo, op )); + IOLockLock(gIOInterruptControllersLock); + + gIOInterruptControllers->removeObject(name); + + IOLockUnlock(gIOInterruptControllersLock); + + return kIOReturnSuccess; } -IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController) +IOInterruptController * +IOPlatformExpert::lookUpInterruptController(OSSymbol *name) { - IOLockLock(gIOInterruptControllersLock); - - gIOInterruptControllers->setObject(name, interruptController); - - IOLockWakeup(gIOInterruptControllersLock, - gIOInterruptControllers, /* one-thread */ false); + OSObject *object; + + IOLockLock(gIOInterruptControllersLock); + while (1) { + object = gIOInterruptControllers->getObject(name); - IOLockUnlock(gIOInterruptControllersLock); - - return kIOReturnSuccess; + if (object != NULL) { + break; + } + + IOLockSleep(gIOInterruptControllersLock, + gIOInterruptControllers, THREAD_UNINT); + } + + IOLockUnlock(gIOInterruptControllersLock); + return OSDynamicCast(IOInterruptController, object); } -IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name) + +void +IOPlatformExpert::setCPUInterruptProperties(IOService *service) { - OSObject *object; - - IOLockLock(gIOInterruptControllersLock); - while (1) { - - object = gIOInterruptControllers->getObject(name); - - if (object != 0) - break; - - IOLockSleep(gIOInterruptControllersLock, - gIOInterruptControllers, THREAD_UNINT); - } - - IOLockUnlock(gIOInterruptControllersLock); - return OSDynamicCast(IOInterruptController, object); + IOCPUInterruptController *controller; + + controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController"))); + if (controller) { + controller->setCPUInterruptProperties(service); + } } +bool +IOPlatformExpert::atInterruptLevel(void) +{ + return ml_at_interrupt_context(); +} -void IOPlatformExpert::setCPUInterruptProperties(IOService *service) +bool +IOPlatformExpert::platformAdjustService(IOService */*service*/) { - IOCPUInterruptController *controller; - - controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController"))); - if (controller) controller->setCPUInterruptProperties(service); + return true; } -bool IOPlatformExpert::atInterruptLevel(void) +void +IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs) { - return ml_at_interrupt_context(); + *secs = getGMTTimeOfDay(); + *nsecs = 0; } -bool IOPlatformExpert::platformAdjustService(IOService */*service*/) +void +IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs) { - return true; + setGMTTimeOfDay(secs); } @@ -369,52 +478,19 @@ bool IOPlatformExpert::platformAdjustService(IOService */*service*/) // //********************************************************************************* -void IOPlatformExpert:: +void +IOPlatformExpert:: PMLog(const char *who, unsigned long event, - unsigned long param1, unsigned long param2) + unsigned long param1, unsigned long param2) { - UInt32 debugFlags = gIOKitDebug; - UInt32 traceFlags = gIOKitTrace; - uintptr_t name = 0; - UInt32 i = 0; - - if (debugFlags & kIOLogPower) { - clock_sec_t nows; clock_usec_t nowus; clock_get_system_microtime(&nows, &nowus); nowus += (nows % 1000) * 1000000; - kprintf("pm%u %p %.30s %d %lx %lx\n", - nowus, current_thread(), who, // Identity - (int) event, (long) param1, (long) param2); // Args - - if (traceFlags & kIOTracePowerMgmt) { - static const UInt32 sStartStopBitField[] = - { 0x00000000, 0x00000040 }; // Only Program Hardware so far - - // Arcane formula from Hacker's Delight by Warren - // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31)) - UInt32 sgnevent = ((long) event >> 31); - UInt32 absevent = sgnevent ^ (event + sgnevent); - UInt32 code = IODBG_POWER(absevent); - - UInt32 bit = 1 << (absevent & 0x1f); - if (absevent < sizeof(sStartStopBitField) * 8 - && (sStartStopBitField[absevent >> 5] & bit) ) { - // Or in the START or END bits, Start = 1 & END = 2 - // If sgnevent == 0 then START - 0 => START - // else if sgnevent == -1 then START - -1 => END - code |= DBG_FUNC_START - sgnevent; - } - - // Get first 8 characters of the name - while ( i < sizeof(uintptr_t) && who[i] != 0) - { ((char *)&name)[sizeof(uintptr_t)-i-1]=who[i]; i++; } - // Record the timestamp. - IOTimeStampConstant(code, name, event, param1, param2); - } - } + kprintf("pm%u %p %.30s %d %lx %lx\n", + nowus, OBFUSCATE(current_thread()), who, // Identity + (int) event, (long)OBFUSCATE(param1), (long)OBFUSCATE(param2)); // Args } @@ -423,16 +499,17 @@ PMLog(const char *who, unsigned long event, // // In this vanilla implementation, a Root Power Domain is instantiated. // All other objects which register will be children of this Root. -// Where this is inappropriate, PMInstantiatePowerDomains is overridden +// Where this is inappropriate, PMInstantiatePowerDomains is overridden // in a platform-specific subclass. //********************************************************************************* -void IOPlatformExpert::PMInstantiatePowerDomains ( void ) +void +IOPlatformExpert::PMInstantiatePowerDomains( void ) { - root = new IOPMrootDomain; - root->init(); - root->attach(this); - root->start(this); + root = new IOPMrootDomain; + root->init(); + root->attach(this); + root->start(this); } @@ -443,9 +520,10 @@ void IOPlatformExpert::PMInstantiatePowerDomains ( void ) // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass. //********************************************************************************* -void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice) +void +IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice) { - root->addPowerChild ( theDevice ); + root->addPowerChild( theDevice ); } //********************************************************************************* @@ -453,9 +531,10 @@ void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevic // //********************************************************************************* -bool IOPlatformExpert::hasPMFeature (unsigned long featureMask) +bool +IOPlatformExpert::hasPMFeature(unsigned long featureMask) { - return ((_pePMFeatures & featureMask) != 0); + return (_pePMFeatures & featureMask) != 0; } //********************************************************************************* @@ -463,9 +542,10 @@ bool IOPlatformExpert::hasPMFeature (unsigned long featureMask) // //********************************************************************************* -bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask) +bool +IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask) { - return ((_pePrivPMFeatures & privFeatureMask) != 0); + return (_pePrivPMFeatures & privFeatureMask) != 0; } //********************************************************************************* @@ -473,9 +553,10 @@ bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask) // //********************************************************************************* -int IOPlatformExpert::numBatteriesSupported (void) +int +IOPlatformExpert::numBatteriesSupported(void) { - return (_peNumBatteriesSupported); + return _peNumBatteriesSupported; } //********************************************************************************* @@ -489,99 +570,102 @@ int IOPlatformExpert::numBatteriesSupported (void) // registered for the given service. //********************************************************************************* -bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent) -{ - unsigned int i; - unsigned int numPowerTreeNodes; - OSDictionary * entry; - OSDictionary * matchingDictionary; - OSDictionary * providerDictionary; - OSDictionary * deviceDictionary; - OSDictionary * nubDictionary; - OSArray * children; - bool nodeFound = false; - bool continueSearch = false; - bool deviceMatch = false; - bool providerMatch = false; - bool multiParentMatch = false; - - if ( (NULL == theDevice) || (NULL == inSubTree) ) - return false; - - numPowerTreeNodes = inSubTree->getCount (); - - // iterate through the power tree to find a home for this device - - for ( i = 0; i < numPowerTreeNodes; i++ ) { - - entry = (OSDictionary *) inSubTree->getObject (i); - - matchingDictionary = (OSDictionary *) entry->getObject ("device"); - providerDictionary = (OSDictionary *) entry->getObject ("provider"); - - deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match - if ( matchingDictionary ) { - deviceMatch = false; - if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) { - deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary ); - deviceDictionary->release (); - } - } - - providerMatch = true; // we indicate a match if there is no nub or provider - if ( theNub && providerDictionary ) { - providerMatch = false; - if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) { - providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary ); - nubDictionary->release (); - } - } - - multiParentMatch = true; // again we indicate a match if there is no multi-parent node - if (deviceMatch && providerMatch) { - if (NULL != multipleParentKeyValue) { - OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent"); - multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false; - } - } - - nodeFound = (deviceMatch && providerMatch && multiParentMatch); - - // if the power tree specifies a provider dictionary but theNub is - // NULL then we cannot match with this entry. - - if ( theNub == NULL && providerDictionary != NULL ) - nodeFound = false; - - // if this node is THE ONE...then register the device - - if ( nodeFound ) { - if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) { - - if ( kIOLogPower & gIOKitDebug) - IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n"); - - numInstancesRegistered++; - - // determine if we need to search for additional nodes for this item - multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent"); - } - else - nodeFound = false; - } - - continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) ); - - if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) { - nodeFound = CheckSubTree ( children, theNub, theDevice, entry ); - continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) ); - } +bool +IOPlatformExpert::CheckSubTree(OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent) +{ + unsigned int i; + unsigned int numPowerTreeNodes; + OSDictionary * entry; + OSDictionary * matchingDictionary; + OSDictionary * providerDictionary; + OSDictionary * deviceDictionary; + OSDictionary * nubDictionary; + OSArray * children; + bool nodeFound = false; + bool continueSearch = false; + bool deviceMatch = false; + bool providerMatch = false; + bool multiParentMatch = false; + + if ((NULL == theDevice) || (NULL == inSubTree)) { + return false; + } - if ( false == continueSearch ) - break; - } + numPowerTreeNodes = inSubTree->getCount(); + + // iterate through the power tree to find a home for this device + + for (i = 0; i < numPowerTreeNodes; i++) { + entry = (OSDictionary *) inSubTree->getObject(i); + + matchingDictionary = (OSDictionary *) entry->getObject("device"); + providerDictionary = (OSDictionary *) entry->getObject("provider"); + + deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match + if (matchingDictionary) { + deviceMatch = false; + if (NULL != (deviceDictionary = theDevice->dictionaryWithProperties())) { + deviceMatch = deviceDictionary->isEqualTo( matchingDictionary, matchingDictionary ); + deviceDictionary->release(); + } + } + + providerMatch = true; // we indicate a match if there is no nub or provider + if (theNub && providerDictionary) { + providerMatch = false; + if (NULL != (nubDictionary = theNub->dictionaryWithProperties())) { + providerMatch = nubDictionary->isEqualTo( providerDictionary, providerDictionary ); + nubDictionary->release(); + } + } + + multiParentMatch = true; // again we indicate a match if there is no multi-parent node + if (deviceMatch && providerMatch) { + if (NULL != multipleParentKeyValue) { + OSNumber * aNumber = (OSNumber *) entry->getObject("multiple-parent"); + multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo(aNumber) : false; + } + } + + nodeFound = (deviceMatch && providerMatch && multiParentMatch); + + // if the power tree specifies a provider dictionary but theNub is + // NULL then we cannot match with this entry. + + if (theNub == NULL && providerDictionary != NULL) { + nodeFound = false; + } + + // if this node is THE ONE...then register the device + + if (nodeFound) { + if (RegisterServiceInTree(theDevice, entry, theParent, theNub)) { + if (kIOLogPower & gIOKitDebug) { + IOLog("PMRegisterDevice/CheckSubTree - service registered!\n"); + } + + numInstancesRegistered++; + + // determine if we need to search for additional nodes for this item + multipleParentKeyValue = (OSNumber *) entry->getObject("multiple-parent"); + } else { + nodeFound = false; + } + } + + continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue)); + + if (continueSearch && (NULL != (children = (OSArray *) entry->getObject("children")))) { + nodeFound = CheckSubTree( children, theNub, theDevice, entry ); + continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue)); + } + + if (false == continueSearch) { + break; + } + } - return ( nodeFound ); + return nodeFound; } //********************************************************************************* @@ -590,51 +674,53 @@ bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IO // Register a device at the specified node of our power tree. //********************************************************************************* -bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider) -{ - IOService * aService; - bool registered = false; - OSArray * children; - unsigned int numChildren; - OSDictionary * child; - - // make sure someone is not already registered here - - if ( NULL == theTreeNode->getObject ("service") ) { - - if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) { - - // 1. CHILDREN ------------------ - - // we registered the node in the tree...now if the node has children - // registered we must tell this service to add them. - - if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) { - numChildren = children->getCount (); - for ( unsigned int i = 0; i < numChildren; i++ ) { - if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) { - if ( NULL != (aService = (IOService *) child->getObject ("service")) ) - theService->addPowerChild (aService); - } - } - } - - // 2. PARENT -------------------- - - // also we must notify the parent of this node (if a registered service - // exists there) of a new child. - - if ( theTreeParentNode ) { - if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) ) - if (aService != theProvider) - aService->addPowerChild (theService); - } - - registered = true; - } - } +bool +IOPlatformExpert::RegisterServiceInTree(IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider) +{ + IOService * aService; + bool registered = false; + OSArray * children; + unsigned int numChildren; + OSDictionary * child; + + // make sure someone is not already registered here + + if (NULL == theTreeNode->getObject("service")) { + if (theTreeNode->setObject("service", OSDynamicCast( OSObject, theService))) { + // 1. CHILDREN ------------------ + + // we registered the node in the tree...now if the node has children + // registered we must tell this service to add them. + + if (NULL != (children = (OSArray *) theTreeNode->getObject("children"))) { + numChildren = children->getCount(); + for (unsigned int i = 0; i < numChildren; i++) { + if (NULL != (child = (OSDictionary *) children->getObject(i))) { + if (NULL != (aService = (IOService *) child->getObject("service"))) { + theService->addPowerChild(aService); + } + } + } + } + + // 2. PARENT -------------------- + + // also we must notify the parent of this node (if a registered service + // exists there) of a new child. + + if (theTreeParentNode) { + if (NULL != (aService = (IOService *) theTreeParentNode->getObject("service"))) { + if (aService != theProvider) { + aService->addPowerChild(theService); + } + } + } + + registered = true; + } + } - return registered; + return registered; } //********************************************************************************* @@ -642,444 +728,737 @@ bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictiona // // Print the keys for the given dictionary and selected contents. //********************************************************************************* -void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg) +void +printDictionaryKeys(OSDictionary * inDictionary, char * inMsg) { - OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary); - OSSymbol * mkey; - OSString * ioClass; - unsigned int i = 0; - - mcoll->reset (); - - mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ()); + OSCollectionIterator * mcoll = OSCollectionIterator::withCollection(inDictionary); + OSSymbol * mkey; + OSString * ioClass; + unsigned int i = 0; - while (mkey) { + mcoll->reset(); - // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () ); + mkey = OSDynamicCast(OSSymbol, mcoll->getNextObject()); - // if this is the IOClass key, print it's contents + while (mkey) { + // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () ); - if ( mkey->isEqualTo ("IOClass") ) { - ioClass = (OSString *) inDictionary->getObject ("IOClass"); - if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () ); - } + // if this is the IOClass key, print it's contents - // if this is an IOProviderClass key print it + if (mkey->isEqualTo("IOClass")) { + ioClass = (OSString *) inDictionary->getObject("IOClass"); + if (ioClass) { + IOLog("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy()); + } + } - if ( mkey->isEqualTo ("IOProviderClass") ) { - ioClass = (OSString *) inDictionary->getObject ("IOProviderClass"); - if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () ); + // if this is an IOProviderClass key print it - } + if (mkey->isEqualTo("IOProviderClass")) { + ioClass = (OSString *) inDictionary->getObject("IOProviderClass"); + if (ioClass) { + IOLog("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy()); + } + } - // also print IONameMatch keys - if ( mkey->isEqualTo ("IONameMatch") ) { - ioClass = (OSString *) inDictionary->getObject ("IONameMatch"); - if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () ); - } + // also print IONameMatch keys + if (mkey->isEqualTo("IONameMatch")) { + ioClass = (OSString *) inDictionary->getObject("IONameMatch"); + if (ioClass) { + IOLog("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy()); + } + } - // also print IONameMatched keys + // also print IONameMatched keys - if ( mkey->isEqualTo ("IONameMatched") ) { - ioClass = (OSString *) inDictionary->getObject ("IONameMatched"); - if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () ); - } + if (mkey->isEqualTo("IONameMatched")) { + ioClass = (OSString *) inDictionary->getObject("IONameMatched"); + if (ioClass) { + IOLog("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy()); + } + } #if 0 - // print clock-id - - if ( mkey->isEqualTo ("AAPL,clock-id") ) { - char * cstr; - cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id")); - if (cstr) - kprintf (" ===> AAPL,clock-id is %s\n", cstr ); - } + // print clock-id + + if (mkey->isEqualTo("AAPL,clock-id")) { + char * cstr; + cstr = getCStringForObject(inDictionary->getObject("AAPL,clock-id")); + if (cstr) { + kprintf(" ===> AAPL,clock-id is %s\n", cstr ); + } + } #endif - // print name + // print name - if ( mkey->isEqualTo ("name") ) { - char nameStr[64]; - nameStr[0] = 0; - getCStringForObject(inDictionary->getObject("name"), nameStr, - sizeof(nameStr)); - if (strlen(nameStr) > 0) - IOLog ("%s name is %s\n", inMsg, nameStr); - } + if (mkey->isEqualTo("name")) { + char nameStr[64]; + nameStr[0] = 0; + getCStringForObject(inDictionary->getObject("name"), nameStr, + sizeof(nameStr)); + if (strlen(nameStr) > 0) { + IOLog("%s name is %s\n", inMsg, nameStr); + } + } - mkey = (OSSymbol *) mcoll->getNextObject (); + mkey = (OSSymbol *) mcoll->getNextObject(); - i++; - } + i++; + } - mcoll->release (); + mcoll->release(); } static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen) { - char * buffer; - unsigned int len, i; - - if ( (NULL == inObj) || (NULL == outStr)) - return; - - char * objString = (char *) (inObj->getMetaClass())->getClassName(); + char * buffer; + unsigned int len, i; - if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) || - (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol")))) - strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen); + if ((NULL == inObj) || (NULL == outStr)) { + return; + } - else if (0 == strncmp(objString, "OSData", sizeof("OSData"))) { - len = ((OSData *)inObj)->getLength(); - buffer = (char *)((OSData *)inObj)->getBytesNoCopy(); - if (buffer && (len > 0)) { - for (i=0; i < len; i++) { - outStr[i] = buffer[i]; - } - outStr[len] = 0; - } - } + char * objString = (char *) (inObj->getMetaClass())->getClassName(); + + if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) || + (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol")))) { + strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen); + } else if (0 == strncmp(objString, "OSData", sizeof("OSData"))) { + len = ((OSData *)inObj)->getLength(); + buffer = (char *)((OSData *)inObj)->getBytesNoCopy(); + if (buffer && (len > 0)) { + for (i = 0; i < len; i++) { + outStr[i] = buffer[i]; + } + outStr[len] = 0; + } + } } /* IOShutdownNotificationsTimedOut * - Called from a timer installed by PEHaltRestart */ -static void IOShutdownNotificationsTimedOut( - thread_call_param_t p0, - thread_call_param_t p1) +#ifdef CONFIG_EMBEDDED +__abortlike +#endif +static void +IOShutdownNotificationsTimedOut( + thread_call_param_t p0, + thread_call_param_t p1) { #ifdef CONFIG_EMBEDDED - /* 30 seconds has elapsed - panic */ - panic("Halt/Restart Timed Out"); + /* 30 seconds has elapsed - panic */ + panic("Halt/Restart Timed Out"); #else /* ! CONFIG_EMBEDDED */ - int type = (int)(long)p0; + int type = (int)(long)p0; + uint32_t timeout = (uint32_t)(uintptr_t)p1; + + IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain(); + if (pmRootDomain) { + if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2) || pmRootDomain->checkShutdownTimeout()) { + pmRootDomain->panicWithShutdownLog(timeout * 1000); + } + } - /* 30 seconds has elapsed - resume shutdown */ - if(gIOPlatform) gIOPlatform->haltRestart(type); + /* 30 seconds has elapsed - resume shutdown */ + if (gIOPlatform) { + gIOPlatform->haltRestart(type); + } #endif /* CONFIG_EMBEDDED */ } extern "C" { - /* * Callouts from BSD for machine name & model - */ + */ -boolean_t PEGetMachineName( char * name, int maxLength ) +boolean_t +PEGetMachineName( char * name, int maxLength ) { - if( gIOPlatform) - return( gIOPlatform->getMachineName( name, maxLength )); - else - return( false ); + if (gIOPlatform) { + return gIOPlatform->getMachineName( name, maxLength ); + } else { + return false; + } } -boolean_t PEGetModelName( char * name, int maxLength ) +boolean_t +PEGetModelName( char * name, int maxLength ) { - if( gIOPlatform) - return( gIOPlatform->getModelName( name, maxLength )); - else - return( false ); + if (gIOPlatform) { + return gIOPlatform->getModelName( name, maxLength ); + } else { + return false; + } } -int PEGetPlatformEpoch(void) +int +PEGetPlatformEpoch(void) { - if( gIOPlatform) - return( gIOPlatform->getBootROMType()); - else - return( -1 ); + if (gIOPlatform) { + return gIOPlatform->getBootROMType(); + } else { + return -1; + } } -int PEHaltRestart(unsigned int type) -{ - IOPMrootDomain *pmRootDomain; - AbsoluteTime deadline; - thread_call_t shutdown_hang; - - if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU) - { - pmRootDomain = IOService::getPMRootDomain(); - /* Notify IOKit PM clients of shutdown/restart - Clients subscribe to this message with a call to - IOService::registerInterest() - */ - - /* Spawn a thread that will panic in 30 seconds. - If all goes well the machine will be off by the time - the timer expires. - */ - shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut, - (thread_call_param_t) type); - clock_interval_to_deadline( 30, kSecondScale, &deadline ); - thread_call_enter1_delayed( shutdown_hang, 0, deadline ); +int +PEHaltRestart(unsigned int type) +{ + IOPMrootDomain *pmRootDomain; + AbsoluteTime deadline; + thread_call_t shutdown_hang; + IORegistryEntry *node; + OSData *data; + uint32_t timeout = kShutdownTimeout; + static boolean_t panic_begin_called = FALSE; + + if (type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU) { + /* If we're in the panic path, the locks and memory allocations required below + * could fail. So just try to reboot instead of risking a nested panic. + */ + if (panic_begin_called) { + goto skip_to_haltRestart; + } + + pmRootDomain = IOService::getPMRootDomain(); + /* Notify IOKit PM clients of shutdown/restart + * Clients subscribe to this message with a call to + * IOService::registerInterest() + */ + + /* Spawn a thread that will panic in 30 seconds. + * If all goes well the machine will be off by the time + * the timer expires. If the device wants a different + * timeout, use that value instead of 30 seconds. + */ +#if CONFIG_EMBEDDED +#define RESTART_NODE_PATH "/defaults" +#else +#define RESTART_NODE_PATH "/chosen" +#endif + node = IORegistryEntry::fromPath( RESTART_NODE_PATH, gIODTPlane ); + if (node) { + data = OSDynamicCast( OSData, node->getProperty( "halt-restart-timeout" )); + if (data && data->getLength() == 4) { + timeout = *((uint32_t *) data->getBytesNoCopy()); + } + } + +#if (DEVELOPMENT || DEBUG) + /* Override the default timeout via a boot-arg */ + uint32_t boot_arg_val; + if (PE_parse_boot_argn("halt_restart_timeout", &boot_arg_val, sizeof(boot_arg_val))) { + timeout = boot_arg_val; + } +#endif - pmRootDomain->handlePlatformHaltRestart(type); - /* This notification should have few clients who all do - their work synchronously. - - In this "shutdown notification" context we don't give - drivers the option of working asynchronously and responding - later. PM internals make it very hard to wait for asynchronous - replies. - */ - } + if (timeout) { + shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut, + (thread_call_param_t)(uintptr_t) type); + clock_interval_to_deadline( timeout, kSecondScale, &deadline ); + thread_call_enter1_delayed( shutdown_hang, (thread_call_param_t)(uintptr_t)timeout, deadline ); + } + + pmRootDomain->handlePlatformHaltRestart(type); + /* This notification should have few clients who all do + * their work synchronously. + * + * In this "shutdown notification" context we don't give + * drivers the option of working asynchronously and responding + * later. PM internals make it very hard to wait for asynchronous + * replies. + */ + } else if (type == kPEPanicRestartCPU || type == kPEPanicSync || type == kPEPanicRestartCPUNoPanicEndCallouts || + type == kPEPanicRestartCPUNoCallouts) { + if (type == kPEPanicRestartCPU) { + // Notify any listeners that we're done collecting + // panic data before we call through to do the restart +#if !CONFIG_EMBEDDED + if (coprocessor_cross_panic_enabled) +#endif + IOCPURunPlatformPanicActions(kPEPanicEnd); + } + + if ((type == kPEPanicRestartCPU) || (type == kPEPanicRestartCPUNoPanicEndCallouts)) { + // Callout to shutdown the disk driver once we've returned from the + // kPEPanicEnd callbacks (if appropriate) and we know all coredumps + // on this system are complete). + IOCPURunPlatformPanicActions(kPEPanicDiskShutdown); + } + + if (type == kPEPanicRestartCPUNoPanicEndCallouts || type == kPEPanicRestartCPUNoCallouts) { + // Replace the wrapper type with the type drivers handle + type = kPEPanicRestartCPU; + } + + // Do an initial sync to flush as much panic data as possible, + // in case we have a problem in one of the platorm panic handlers. + // After running the platform handlers, do a final sync w/ + // platform hardware quiesced for the panic. + PE_sync_panic_buffers(); + IOCPURunPlatformPanicActions(type); + PE_sync_panic_buffers(); + } else if (type == kPEPanicEnd) { +#if !CONFIG_EMBEDDED + if (coprocessor_cross_panic_enabled) +#endif + IOCPURunPlatformPanicActions(type); + } else if (type == kPEPanicBegin) { +#if !CONFIG_EMBEDDED + if (coprocessor_cross_panic_enabled) +#endif + { + // Only call the kPEPanicBegin callout once + if (!panic_begin_called) { + panic_begin_called = TRUE; + IOCPURunPlatformPanicActions(type); + } + } + } - if (gIOPlatform) return gIOPlatform->haltRestart(type); - else return -1; +skip_to_haltRestart: + if (gIOPlatform) { + return gIOPlatform->haltRestart(type); + } else { + return -1; + } } -UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length) +UInt32 +PESavePanicInfo(UInt8 *buffer, UInt32 length) { - if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length); - else return 0; + if (gIOPlatform != NULL) { + return gIOPlatform->savePanicInfo(buffer, length); + } else { + return 0; + } } +void +PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length) +{ + IOCPURunPlatformPanicSyncAction(buffer, offset, length); + return; +} -inline static int init_gIOOptionsEntry(void) +inline static int +init_gIOOptionsEntry(void) { - IORegistryEntry *entry; - void *nvram_entry; - volatile void **options; - int ret = -1; + IORegistryEntry *entry; + void *nvram_entry; + volatile void **options; + int ret = -1; - if (gIOOptionsEntry) - return 0; + if (gIOOptionsEntry) { + return 0; + } - entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); - if (!entry) - return -1; + entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); + if (!entry) { + return -1; + } - nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry); - if (!nvram_entry) - goto release; + nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry); + if (!nvram_entry) { + goto release; + } - options = (volatile void **) &gIOOptionsEntry; - if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) { - ret = 0; - goto release; - } + options = (volatile void **) &gIOOptionsEntry; + if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) { + ret = 0; + goto release; + } - return 0; + return 0; release: - entry->release(); - return ret; - + entry->release(); + return ret; } /* pass in a NULL value if you just want to figure out the len */ -boolean_t PEReadNVRAMProperty(const char *symbol, void *value, - unsigned int *len) +boolean_t +PEReadNVRAMProperty(const char *symbol, void *value, + unsigned int *len) { - OSObject *obj; - OSData *data; - unsigned int vlen; + OSObject *obj; + OSData *data; + unsigned int vlen; - if (!symbol || !len) - goto err; + if (!symbol || !len) { + goto err; + } - if (init_gIOOptionsEntry() < 0) - goto err; + if (init_gIOOptionsEntry() < 0) { + goto err; + } - vlen = *len; - *len = 0; + vlen = *len; + *len = 0; - obj = gIOOptionsEntry->getProperty(symbol); - if (!obj) - goto err; + obj = gIOOptionsEntry->getProperty(symbol); + if (!obj) { + goto err; + } - /* convert to data */ - data = OSDynamicCast(OSData, obj); - if (!data) - goto err; + /* convert to data */ + data = OSDynamicCast(OSData, obj); + if (!data) { + goto err; + } - *len = data->getLength(); - vlen = min(vlen, *len); - if (vlen) - memcpy((void *) value, data->getBytesNoCopy(), vlen); + *len = data->getLength(); + vlen = min(vlen, *len); + if (value && vlen) { + memcpy((void *) value, data->getBytesNoCopy(), vlen); + } - return TRUE; + return TRUE; err: - return FALSE; + return FALSE; } +boolean_t +PEWriteNVRAMBooleanProperty(const char *symbol, boolean_t value) +{ + const OSSymbol *sym = NULL; + OSBoolean *data = NULL; + bool ret = false; + + if (symbol == NULL) { + goto exit; + } + + if (init_gIOOptionsEntry() < 0) { + goto exit; + } + + if ((sym = OSSymbol::withCStringNoCopy(symbol)) == NULL) { + goto exit; + } + + data = value ? kOSBooleanTrue : kOSBooleanFalse; + ret = gIOOptionsEntry->setProperty(sym, data); + + sym->release(); + + /* success, force the NVRAM to flush writes */ + if (ret == true) { + gIOOptionsEntry->sync(); + } + +exit: + return ret; +} -boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value, - const unsigned int len) +static boolean_t +PEWriteNVRAMPropertyInternal(const char *symbol, boolean_t copySymbol, const void *value, + const unsigned int len) { - const OSSymbol *sym; - OSData *data; - bool ret = false; + const OSSymbol *sym; + OSData *data; + bool ret = false; - if (!symbol || !value || !len) - goto err; + if (!symbol || !value || !len) { + goto err; + } - if (init_gIOOptionsEntry() < 0) - goto err; + if (init_gIOOptionsEntry() < 0) { + goto err; + } - sym = OSSymbol::withCStringNoCopy(symbol); - if (!sym) - goto err; + if (copySymbol == TRUE) { + sym = OSSymbol::withCString(symbol); + } else { + sym = OSSymbol::withCStringNoCopy(symbol); + } - data = OSData::withBytes((void *) value, len); - if (!data) - goto sym_done; + if (!sym) { + goto err; + } - ret = gIOOptionsEntry->setProperty(sym, data); - data->release(); + data = OSData::withBytes((void *) value, len); + if (!data) { + goto sym_done; + } + + ret = gIOOptionsEntry->setProperty(sym, data); + data->release(); sym_done: - sym->release(); + sym->release(); - if (ret == true) { - gIOOptionsEntry->sync(); - return TRUE; - } + if (ret == true) { + gIOOptionsEntry->sync(); + return TRUE; + } err: - return FALSE; + return FALSE; } +boolean_t +PEWriteNVRAMProperty(const char *symbol, const void *value, + const unsigned int len) +{ + return PEWriteNVRAMPropertyInternal(symbol, FALSE, value, len); +} -long PEGetGMTTimeOfDay(void) +boolean_t +PEWriteNVRAMPropertyWithCopy(const char *symbol, const void *value, + const unsigned int len) { - long result = 0; + return PEWriteNVRAMPropertyInternal(symbol, TRUE, value, len); +} - if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay(); +boolean_t +PERemoveNVRAMProperty(const char *symbol) +{ + const OSSymbol *sym; - return (result); + if (!symbol) { + goto err; + } + + if (init_gIOOptionsEntry() < 0) { + goto err; + } + + sym = OSSymbol::withCStringNoCopy(symbol); + if (!sym) { + goto err; + } + + gIOOptionsEntry->removeProperty(sym); + + sym->release(); + + gIOOptionsEntry->sync(); + return TRUE; + +err: + return FALSE; } -void PESetGMTTimeOfDay(long secs) +long +PEGetGMTTimeOfDay(void) { - if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs); + clock_sec_t secs; + clock_usec_t usecs; + + PEGetUTCTimeOfDay(&secs, &usecs); + return secs; +} + +void +PESetGMTTimeOfDay(long secs) +{ + PESetUTCTimeOfDay(secs, 0); +} + +void +PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs) +{ + clock_nsec_t nsecs = 0; + + *secs = 0; + if (gIOPlatform) { + gIOPlatform->getUTCTimeOfDay(secs, &nsecs); + } + + assert(nsecs < NSEC_PER_SEC); + *usecs = nsecs / NSEC_PER_USEC; } +void +PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs) +{ + assert(usecs < USEC_PER_SEC); + if (gIOPlatform) { + gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC); + } +} + +coprocessor_type_t +PEGetCoprocessorVersion( void ) +{ + coprocessor_type_t coprocessor_version = kCoprocessorVersionNone; +#if !CONFIG_EMBEDDED + IORegistryEntry *platform_entry = NULL; + OSData *coprocessor_version_obj = NULL; + + platform_entry = IORegistryEntry::fromPath(kIODeviceTreePlane ":/efi/platform"); + if (platform_entry != NULL) { + coprocessor_version_obj = OSDynamicCast(OSData, platform_entry->getProperty("apple-coprocessor-version")); + if ((coprocessor_version_obj != NULL) && (coprocessor_version_obj->getLength() <= sizeof(uint64_t))) { + memcpy(&coprocessor_version, coprocessor_version_obj->getBytesNoCopy(), coprocessor_version_obj->getLength()); + } + platform_entry->release(); + } +#endif + return coprocessor_version; +} } /* extern "C" */ -void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) +void +IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) { - OSData * data; - IORegistryEntry * entry; - OSString * string = 0; - uuid_string_t uuid; + OSData * data; + IORegistryEntry * entry; + OSString * string = NULL; + uuid_string_t uuid; #if CONFIG_EMBEDDED - entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ); - if ( entry ) - { - OSData * data1; - - data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" ) ); - if ( data1 && data1->getLength( ) == 8 ) - { - OSData * data2; - - data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" ) ); - if ( data2 && data2->getLength( ) == 4 ) - { - SHA1_CTX context; - uint8_t digest[ SHA_DIGEST_LENGTH ]; - const uuid_t space = { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 }; - - SHA1Init( &context ); - SHA1Update( &context, space, sizeof( space ) ); - SHA1Update( &context, data1->getBytesNoCopy( ), data1->getLength( ) ); - SHA1Update( &context, data2->getBytesNoCopy( ), data2->getLength( ) ); - SHA1Final( digest, &context ); - - digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50; - digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80; - - uuid_unparse( digest, uuid ); - string = OSString::withCString( uuid ); - } - } - - entry->release( ); - } -#else /* !CONFIG_EMBEDDED */ - entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane ); - if ( entry ) - { - data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) ); - if ( data && data->getLength( ) == 16 ) - { - SHA1_CTX context; - uint8_t digest[ SHA_DIGEST_LENGTH ]; - const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC }; - - SHA1Init( &context ); - SHA1Update( &context, space, sizeof( space ) ); - SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) ); - SHA1Final( digest, &context ); - - digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50; - digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80; - - uuid_unparse( digest, uuid ); - string = OSString::withCString( uuid ); - } - - entry->release( ); - } -#endif /* !CONFIG_EMBEDDED */ - - if ( string == 0 ) - { - entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); - if ( entry ) - { - data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) ); - if ( data && data->getLength( ) == sizeof( uuid_t ) ) - { - uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid ); - string = OSString::withCString( uuid ); - } - - entry->release( ); - } - } - - if ( string ) - { - getProvider( )->setProperty( kIOPlatformUUIDKey, string ); - publishResource( kIOPlatformUUIDKey, string ); - - string->release( ); - } - - publishResource("IONVRAM"); -} - -IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName, - bool waitForFunction, - void *param1, void *param2, - void *param3, void *param4) -{ - IOService *service, *_resources; - - if (waitForFunction) { - _resources = waitForService(resourceMatching(functionName)); - } else { - _resources = getResourceService(); - } - if (_resources == 0) return kIOReturnUnsupported; - - service = OSDynamicCast(IOService, _resources->getProperty(functionName)); - if (service == 0) return kIOReturnUnsupported; - - return service->callPlatformFunction(functionName, waitForFunction, - param1, param2, param3, param4); -} - -IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) -{ - return 0; + entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ); + if (entry) { + OSData * data1; + + data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" )); + if (data1 && data1->getLength() == 8) { + OSData * data2; + + data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" )); + if (data2 && data2->getLength() == 4) { + SHA1_CTX context; + uint8_t digest[SHA_DIGEST_LENGTH]; + const uuid_t space = { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 }; + + SHA1Init( &context ); + SHA1Update( &context, space, sizeof(space)); + SHA1Update( &context, data1->getBytesNoCopy(), data1->getLength()); + SHA1Update( &context, data2->getBytesNoCopy(), data2->getLength()); + SHA1Final( digest, &context ); + + digest[6] = (digest[6] & 0x0F) | 0x50; + digest[8] = (digest[8] & 0x3F) | 0x80; + + uuid_unparse( digest, uuid ); + string = OSString::withCString( uuid ); + } + } + + entry->release(); + } +#endif /* CONFIG_EMBEDDED */ + +#if defined(XNU_TARGET_OS_OSX) + /* + * If we have panic debugging enabled and the bridgeOS panic SoC watchdog is enabled, + * disable cross panics so that the co-processor doesn't cause the system + * to reset when we enter the debugger or hit a panic on the x86 side. + */ + if (panicDebugging) { + entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); + if (entry) { + data = OSDynamicCast( OSData, entry->getProperty( APPLE_VENDOR_VARIABLE_GUID":BridgeOSPanicWatchdogEnabled" )); + if (data && (data->getLength() == sizeof(UInt8))) { + UInt8 *panicWatchdogEnabled = (UInt8 *) data->getBytesNoCopy(); + UInt32 debug_flags = 0; + if (*panicWatchdogEnabled || (PE_i_can_has_debugger(&debug_flags) && + (debug_flags & DB_DISABLE_CROSS_PANIC))) { + coprocessor_cross_panic_enabled = FALSE; + } + } + entry->release(); + } + } + + entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane ); + if (entry) { + data = OSDynamicCast( OSData, entry->getProperty( "system-id" )); + if (data && data->getLength() == 16) { + SHA1_CTX context; + uint8_t digest[SHA_DIGEST_LENGTH]; + const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC }; + + SHA1Init( &context ); + SHA1Update( &context, space, sizeof(space)); + SHA1Update( &context, data->getBytesNoCopy(), data->getLength()); + SHA1Final( digest, &context ); + + digest[6] = (digest[6] & 0x0F) | 0x50; + digest[8] = (digest[8] & 0x3F) | 0x80; + + uuid_unparse( digest, uuid ); + string = OSString::withCString( uuid ); + } + + entry->release(); + } +#endif /* defined(XNU_TARGET_OS_OSX) */ + + if (string == NULL) { + entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); + if (entry) { + data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" )); + if (data && data->getLength() == sizeof(uuid_t)) { + uuid_unparse((uint8_t *) data->getBytesNoCopy(), uuid ); + string = OSString::withCString( uuid ); + } + + entry->release(); + } + } + + if (string) { + getProvider()->setProperty( kIOPlatformUUIDKey, string ); + publishResource( kIOPlatformUUIDKey, string ); + + string->release(); + } + + publishResource("IONVRAM"); +} + +IOReturn +IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName, + bool waitForFunction, + void *param1, void *param2, + void *param3, void *param4) +{ + IOService *service, *_resources; + + if (functionName == gIOPlatformQuiesceActionKey || + functionName == gIOPlatformActiveActionKey) { + /* + * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction + * must consume that event themselves, without passing it up to super/IOPlatformExpert. + */ + if (gEnforceQuiesceSafety) { + panic("Class %s passed the quiesce/active action to IOPlatformExpert", + getMetaClass()->getClassName()); + } + } + + if (waitForFunction) { + _resources = waitForService(resourceMatching(functionName)); + } else { + _resources = getResourceService(); + } + if (_resources == NULL) { + return kIOReturnUnsupported; + } + + service = OSDynamicCast(IOService, _resources->getProperty(functionName)); + if (service == NULL) { + return kIOReturnUnsupported; + } + + return service->callPlatformFunction(functionName, waitForFunction, + param1, param2, param3, param4); +} + +IOByteCount +IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) +{ + return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -1089,291 +1468,354 @@ IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert ) -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6); -OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6); +OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -IOService * IODTPlatformExpert::probe( IOService * provider, - SInt32 * score ) +IOService * +IODTPlatformExpert::probe( IOService * provider, + SInt32 * score ) { - if( !super::probe( provider, score)) - return( 0 ); + if (!super::probe( provider, score)) { + return NULL; + } - // check machine types - if( !provider->compareNames( getProperty( gIONameMatchKey ) )) - return( 0 ); + // check machine types + if (!provider->compareNames( getProperty( gIONameMatchKey ))) { + return NULL; + } - return( this); + return this; } -bool IODTPlatformExpert::configure( IOService * provider ) +bool +IODTPlatformExpert::configure( IOService * provider ) { - if( !super::configure( provider)) - return( false); + if (!super::configure( provider)) { + return false; + } - processTopLevel( provider ); + processTopLevel( provider ); - return( true ); + return true; } -IOService * IODTPlatformExpert::createNub( IORegistryEntry * from ) +IOService * +IODTPlatformExpert::createNub( IORegistryEntry * from ) { - IOService * nub; + IOService * nub; - nub = new IOPlatformDevice; - if( nub) { - if( !nub->init( from, gIODTPlane )) { - nub->free(); - nub = 0; + nub = new IOPlatformDevice; + if (nub) { + if (!nub->init( from, gIODTPlane )) { + nub->free(); + nub = NULL; + } } - } - return( nub); + return nub; } -bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter ) -{ - IORegistryEntry * next; - IOService * nub; - bool ok = true; - - if( iter) { - while( (next = (IORegistryEntry *) iter->getNextObject())) { - - if( 0 == (nub = createNub( next ))) - continue; - - nub->attach( parent ); - nub->registerService(); - } - iter->release(); - } +bool +IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter ) +{ + IORegistryEntry * next; + IOService * nub; + bool ok = true; + + if (iter) { + while ((next = (IORegistryEntry *) iter->getNextObject())) { + if (NULL == (nub = createNub( next ))) { + continue; + } + + nub->attach( parent ); + nub->registerService(); + } + iter->release(); + } - return( ok ); + return ok; } -void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry ) +void +IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry ) { - OSIterator * kids; - IORegistryEntry * next; - IORegistryEntry * cpus; - IORegistryEntry * options; + OSIterator * kids; + IORegistryEntry * next; + IORegistryEntry * cpus; + IORegistryEntry * options; - // infanticide - kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() ); - if( kids) { - while( (next = (IORegistryEntry *)kids->getNextObject())) { - next->detachAll( gIODTPlane); + // infanticide + kids = IODTFindMatchingEntries( rootEntry, 0, deleteList()); + if (kids) { + while ((next = (IORegistryEntry *)kids->getNextObject())) { + next->detachAll( gIODTPlane); + } + kids->release(); } - kids->release(); - } - // Publish an IODTNVRAM class on /options. - options = rootEntry->childFromPath("options", gIODTPlane); - if (options) { - dtNVRAM = new IODTNVRAM; - if (dtNVRAM) { - if (!dtNVRAM->init(options, gIODTPlane)) { - dtNVRAM->release(); - dtNVRAM = 0; - } else { - dtNVRAM->attach(this); - dtNVRAM->registerService(); + // Publish an IODTNVRAM class on /options. + options = rootEntry->childFromPath("options", gIODTPlane); + if (options) { + dtNVRAM = new IODTNVRAM; + if (dtNVRAM) { + if (!dtNVRAM->init(options, gIODTPlane)) { + dtNVRAM->release(); + dtNVRAM = NULL; + } else { + dtNVRAM->attach(this); + dtNVRAM->registerService(); + options->release(); + } + } } - } - } - // Publish the cpus. - cpus = rootEntry->childFromPath( "cpus", gIODTPlane); - if ( cpus) - createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0)); + // Publish the cpus. + cpus = rootEntry->childFromPath( "cpus", gIODTPlane); + if (cpus) { + createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, NULL)); + cpus->release(); + } - // publish top level, minus excludeList - createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList())); + // publish top level, minus excludeList + createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList())); } -IOReturn IODTPlatformExpert::getNubResources( IOService * nub ) +IOReturn +IODTPlatformExpert::getNubResources( IOService * nub ) { - if( nub->getDeviceMemory()) - return( kIOReturnSuccess ); + if (nub->getDeviceMemory()) { + return kIOReturnSuccess; + } - IODTResolveAddressing( nub, "reg", 0); + IODTResolveAddressing( nub, "reg", NULL); - return( kIOReturnSuccess); + return kIOReturnSuccess; } -bool IODTPlatformExpert::compareNubName( const IOService * nub, - OSString * name, OSString ** matched ) const +bool +IODTPlatformExpert::compareNubName( const IOService * nub, + OSString * name, OSString ** matched ) const { - return( IODTCompareNubName( nub, name, matched ) - || super::compareNubName( nub, name, matched) ); + return IODTCompareNubName( nub, name, matched ) + || super::compareNubName( nub, name, matched); } -bool IODTPlatformExpert::getModelName( char * name, int maxLength ) -{ - OSData * prop; - const char * str; - int len; - char c; - bool ok = false; - - maxLength--; - - prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey ); - if( prop ) { - str = (const char *) prop->getBytesNoCopy(); - - if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) )) - str += strlen( "AAPL," ); - - len = 0; - while( (c = *str++)) { - if( (c == '/') || (c == ' ')) - c = '-'; - - name[ len++ ] = c; - if( len >= maxLength) - break; +bool +IODTPlatformExpert::getModelName( char * name, int maxLength ) +{ + OSData * prop; + const char * str; + int len; + char c; + bool ok = false; + + maxLength--; + + prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey ); + if (prop) { + str = (const char *) prop->getBytesNoCopy(); + + if (0 == strncmp( str, "AAPL,", strlen( "AAPL," ))) { + str += strlen( "AAPL," ); + } + + len = 0; + while ((c = *str++)) { + if ((c == '/') || (c == ' ')) { + c = '-'; + } + + name[len++] = c; + if (len >= maxLength) { + break; + } + } + + name[len] = 0; + ok = true; } - - name[ len ] = 0; - ok = true; - } - return( ok ); + return ok; } -bool IODTPlatformExpert::getMachineName( char * name, int maxLength ) +bool +IODTPlatformExpert::getMachineName( char * name, int maxLength ) { - OSData * prop; - bool ok = false; + OSData * prop; + bool ok = false; - maxLength--; - prop = (OSData *) getProvider()->getProperty( gIODTModelKey ); - ok = (0 != prop); + maxLength--; + prop = (OSData *) getProvider()->getProperty( gIODTModelKey ); + ok = (NULL != prop); - if( ok ) - strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength ); + if (ok) { + strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength ); + } - return( ok ); + return ok; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram ) +void +IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram ) { - if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram); - - super::registerNVRAMController(nvram); + if (dtNVRAM) { + dtNVRAM->registerNVRAMController(nvram); + } + + super::registerNVRAMController(nvram); } -int IODTPlatformExpert::haltRestart(unsigned int type) +int +IODTPlatformExpert::haltRestart(unsigned int type) { - if (dtNVRAM) dtNVRAM->sync(); - - return super::haltRestart(type); + if (dtNVRAM) { + dtNVRAM->sync(); + } + + return super::haltRestart(type); } -IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer, - IOByteCount length) +IOReturn +IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer, + IOByteCount length) { - if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->readXPRAM(offset, buffer, length); + } else { + return kIOReturnNotReady; + } } -IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer, - IOByteCount length) +IOReturn +IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer, + IOByteCount length) { - if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->writeXPRAM(offset, buffer, length); + } else { + return kIOReturnNotReady; + } } -IOReturn IODTPlatformExpert::readNVRAMProperty( +IOReturn +IODTPlatformExpert::readNVRAMProperty( IORegistryEntry * entry, const OSSymbol ** name, OSData ** value ) { - if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->readNVRAMProperty(entry, name, value); + } else { + return kIOReturnNotReady; + } } -IOReturn IODTPlatformExpert::writeNVRAMProperty( +IOReturn +IODTPlatformExpert::writeNVRAMProperty( IORegistryEntry * entry, const OSSymbol * name, OSData * value ) { - if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->writeNVRAMProperty(entry, name, value); + } else { + return kIOReturnNotReady; + } } -OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void) +OSDictionary * +IODTPlatformExpert::getNVRAMPartitions(void) { - if (dtNVRAM) return dtNVRAM->getNVRAMPartitions(); - else return 0; + if (dtNVRAM) { + return dtNVRAM->getNVRAMPartitions(); + } else { + return NULL; + } } -IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID, - IOByteCount offset, UInt8 * buffer, - IOByteCount length) +IOReturn +IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID, + IOByteCount offset, UInt8 * buffer, + IOByteCount length) { - if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset, - buffer, length); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->readNVRAMPartition(partitionID, offset, + buffer, length); + } else { + return kIOReturnNotReady; + } } -IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID, - IOByteCount offset, UInt8 * buffer, - IOByteCount length) +IOReturn +IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID, + IOByteCount offset, UInt8 * buffer, + IOByteCount length) { - if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset, - buffer, length); - else return kIOReturnNotReady; + if (dtNVRAM) { + return dtNVRAM->writeNVRAMPartition(partitionID, offset, + buffer, length); + } else { + return kIOReturnNotReady; + } } -IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) +IOByteCount +IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length) { - IOByteCount lengthSaved = 0; - - if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length); - - if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length); - - return lengthSaved; -} + IOByteCount lengthSaved = 0; + + if (dtNVRAM) { + lengthSaved = dtNVRAM->savePanicInfo(buffer, length); + } -OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) { - UInt8* serialNumber; - unsigned int serialNumberSize; - unsigned short pos = 0; - char* temp; - char SerialNo[30]; - - if (myProperty != NULL) { - serialNumberSize = myProperty->getLength(); - serialNumber = (UInt8*)(myProperty->getBytesNoCopy()); - temp = (char*)serialNumber; - if (serialNumberSize > 0) { - // check to see if this is a CTO serial number... - while (pos < serialNumberSize && temp[pos] != '-') pos++; - - if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number - memcpy(SerialNo, serialNumber + 12, 8); - memcpy(&SerialNo[8], serialNumber, 3); - SerialNo[11] = '-'; - memcpy(&SerialNo[12], serialNumber + 3, 8); - SerialNo[20] = 0; - } else { // just a normal serial number - memcpy(SerialNo, serialNumber + 13, 8); - memcpy(&SerialNo[8], serialNumber, 3); - SerialNo[11] = 0; - } - return OSString::withCString(SerialNo); - } - } - return NULL; + if (lengthSaved == 0) { + lengthSaved = super::savePanicInfo(buffer, length); + } + + return lengthSaved; +} + +OSString* +IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) +{ + UInt8* serialNumber; + unsigned int serialNumberSize; + unsigned short pos = 0; + char* temp; + char SerialNo[30]; + + if (myProperty != NULL) { + serialNumberSize = myProperty->getLength(); + serialNumber = (UInt8*)(myProperty->getBytesNoCopy()); + temp = (char*)serialNumber; + if (serialNumberSize > 0) { + // check to see if this is a CTO serial number... + while (pos < serialNumberSize && temp[pos] != '-') { + pos++; + } + + if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number + memcpy(SerialNo, serialNumber + 12, 8); + memcpy(&SerialNo[8], serialNumber, 3); + SerialNo[11] = '-'; + memcpy(&SerialNo[12], serialNumber + 3, 8); + SerialNo[20] = 0; + } else { // just a normal serial number + memcpy(SerialNo, serialNumber + 13, 8); + memcpy(&SerialNo[8], serialNumber, 3); + SerialNo[11] = 0; + } + return OSString::withCString(SerialNo); + } + } + return NULL; } @@ -1384,106 +1826,105 @@ OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService) -OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0); -OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1); -OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2); -OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3); +OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0); +OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1); +OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2); +OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -bool IOPlatformExpertDevice::compareName( OSString * name, - OSString ** matched ) const +bool +IOPlatformExpertDevice::compareName( OSString * name, + OSString ** matched ) const { - return( IODTCompareNubName( this, name, matched )); + return IODTCompareNubName( this, name, matched ); } bool IOPlatformExpertDevice::initWithArgs( - void * dtTop, void * p2, void * p3, void * p4 ) + void * dtTop, void * p2, void * p3, void * p4 ) { - IORegistryEntry * dt = 0; - void * argsData[ 4 ]; - bool ok; - - // dtTop may be zero on non- device tree systems - if( dtTop && (dt = IODeviceTreeAlloc( dtTop ))) - ok = super::init( dt, gIODTPlane ); - else - ok = super::init(); + IORegistryEntry * dt = NULL; + bool ok; - if( !ok) - return( false); - - workLoop = IOWorkLoop::workLoop(); - if (!workLoop) - return false; + // dtTop may be zero on non- device tree systems + if (dtTop && (dt = IODeviceTreeAlloc( dtTop ))) { + ok = super::init( dt, gIODTPlane ); + } else { + ok = super::init(); + } - argsData[ 0 ] = dtTop; - argsData[ 1 ] = p2; - argsData[ 2 ] = p3; - argsData[ 3 ] = p4; + if (!ok) { + return false; + } - setProperty("IOPlatformArgs", (void *)argsData, sizeof(argsData)); + workLoop = IOWorkLoop::workLoop(); + if (!workLoop) { + return false; + } - return( true); + return true; } -IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const +IOWorkLoop * +IOPlatformExpertDevice::getWorkLoop() const { - return workLoop; + return workLoop; } -IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties ) +IOReturn +IOPlatformExpertDevice::setProperties( OSObject * properties ) { - OSDictionary * dictionary; - OSObject * object; - IOReturn status; - - status = super::setProperties( properties ); - if ( status != kIOReturnUnsupported ) return status; - - status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator ); - if ( status != kIOReturnSuccess ) return status; - - dictionary = OSDynamicCast( OSDictionary, properties ); - if ( dictionary == 0 ) return kIOReturnBadArgument; - - object = dictionary->getObject( kIOPlatformUUIDKey ); - if ( object ) - { - IORegistryEntry * entry; - OSString * string; - uuid_t uuid; - - string = ( OSString * ) getProperty( kIOPlatformUUIDKey ); - if ( string ) return kIOReturnNotPermitted; - - string = OSDynamicCast( OSString, object ); - if ( string == 0 ) return kIOReturnBadArgument; - - status = uuid_parse( string->getCStringNoCopy( ), uuid ); - if ( status != 0 ) return kIOReturnBadArgument; + return kIOReturnUnsupported; +} - entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); - if ( entry ) - { - entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) ); - entry->release( ); - } +IOReturn +IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + IOUserClient ** handler ) +{ + IOReturn err = kIOReturnSuccess; + IOUserClient * newConnect = NULL; + IOUserClient * theConnect = NULL; - setProperty( kIOPlatformUUIDKey, string ); - publishResource( kIOPlatformUUIDKey, string ); + switch (type) { + case kIOKitDiagnosticsClientType: + newConnect = IOKitDiagnosticsClient::withTask(owningTask); + if (!newConnect) { + err = kIOReturnNotPermitted; + } + break; + case kIOKitUserServerClientType: + newConnect = IOUserServer::withTask(owningTask); + if (!newConnect) { + err = kIOReturnNotPermitted; + } + break; + default: + err = kIOReturnBadArgument; + } - return kIOReturnSuccess; - } + if (newConnect) { + if ((false == newConnect->attach(this)) + || (false == newConnect->start(this))) { + newConnect->detach( this ); + newConnect->release(); + err = kIOReturnNotPermitted; + } else { + theConnect = newConnect; + } + } - return kIOReturnUnsupported; + *handler = theConnect; + return err; } -void IOPlatformExpertDevice::free() +void +IOPlatformExpertDevice::free() { - if (workLoop) - workLoop->release(); + if (workLoop) { + workLoop->release(); + } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -1493,28 +1934,31 @@ void IOPlatformExpertDevice::free() OSDefineMetaClassAndStructors(IOPlatformDevice, IOService) -OSMetaClassDefineReservedUnused(IOPlatformDevice, 0); -OSMetaClassDefineReservedUnused(IOPlatformDevice, 1); -OSMetaClassDefineReservedUnused(IOPlatformDevice, 2); -OSMetaClassDefineReservedUnused(IOPlatformDevice, 3); +OSMetaClassDefineReservedUnused(IOPlatformDevice, 0); +OSMetaClassDefineReservedUnused(IOPlatformDevice, 1); +OSMetaClassDefineReservedUnused(IOPlatformDevice, 2); +OSMetaClassDefineReservedUnused(IOPlatformDevice, 3); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -bool IOPlatformDevice::compareName( OSString * name, - OSString ** matched ) const +bool +IOPlatformDevice::compareName( OSString * name, + OSString ** matched ) const { - return( ((IOPlatformExpert *)getProvider())-> - compareNubName( this, name, matched )); + return ((IOPlatformExpert *)getProvider())-> + compareNubName( this, name, matched ); } -IOService * IOPlatformDevice::matchLocation( IOService * /* client */ ) +IOService * +IOPlatformDevice::matchLocation( IOService * /* client */ ) { - return( this ); + return this; } -IOReturn IOPlatformDevice::getResources( void ) +IOReturn +IOPlatformDevice::getResources( void ) { - return( ((IOPlatformExpert *)getProvider())->getNubResources( this )); + return ((IOPlatformExpert *)getProvider())->getNubResources( this ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -1527,24 +1971,27 @@ IOReturn IOPlatformDevice::getResources( void ) *********************************************************************/ class IOPanicPlatform : IOPlatformExpert { - OSDeclareDefaultStructors(IOPanicPlatform); + OSDeclareDefaultStructors(IOPanicPlatform); public: - bool start(IOService * provider); + bool start(IOService * provider) APPLE_KEXT_OVERRIDE; }; OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert); -bool IOPanicPlatform::start(IOService * provider) { - const char * platform_name = "(unknown platform name)"; +bool +IOPanicPlatform::start(IOService * provider) +{ + const char * platform_name = "(unknown platform name)"; - if (provider) platform_name = provider->getName(); + if (provider) { + platform_name = provider->getName(); + } - panic("Unable to find driver for this platform: \"%s\".\n", - platform_name); + panic("Unable to find driver for this platform: \"%s\".\n", + platform_name); - return false; + return false; } -