/*
- * 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
* 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,
* 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 <IOKit/IOCPU.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOKitDebug.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOTimeStamp.h>
#include <IOKit/IOUserClient.h>
+#include <IOKit/IOKitDiagnosticsUserClient.h>
+#include <IOKit/IOUserServer.h>
#include <IOKit/system.h>
+#include <sys/csr.h>
#include <libkern/c++/OSContainers.h>
#include <libkern/crypto/sha1.h>
#include <uuid/uuid.h>
}
-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.
+ *
+ * <rdar://problem/33831837> 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);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-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);
-
- // 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) );
+bool
+IOPlatformExpert::attach( IOService * provider )
+{
+ if (!super::attach( provider )) {
+ return false;
+ }
+
+ 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( 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();
- }
- }
+ 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 */
+ }
- return( true );
+ // Register the presence or lack thereof a system
+ // PCI address mapper with the IOMapper class
+ IOMapper::setMapperRequired(NULL != 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();
+ }
+ }
+
+#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));
+ return PE_current_console( consoleInfo);
}
-IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
- unsigned int op)
+IOReturn
+IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
+ unsigned int op)
{
- return( PE_initialize_console( consoleInfo, op ));
+ return PE_initialize_console( consoleInfo, op );
}
-IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
+IOReturn
+IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
{
- IOLockLock(gIOInterruptControllersLock);
-
- gIOInterruptControllers->setObject(name, interruptController);
-
- IOLockWakeup(gIOInterruptControllersLock,
- gIOInterruptControllers, /* one-thread */ false);
+ IOLockLock(gIOInterruptControllersLock);
+
+ gIOInterruptControllers->setObject(name, interruptController);
- IOLockUnlock(gIOInterruptControllersLock);
-
- return kIOReturnSuccess;
+ IOLockWakeup(gIOInterruptControllersLock,
+ gIOInterruptControllers, /* one-thread */ false);
+
+ IOLockUnlock(gIOInterruptControllersLock);
+
+ return kIOReturnSuccess;
}
-IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
+IOReturn
+IOPlatformExpert::deregisterInterruptController(OSSymbol *name)
{
- 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);
+ IOLockLock(gIOInterruptControllersLock);
+
+ gIOInterruptControllers->removeObject(name);
+
+ IOLockUnlock(gIOInterruptControllersLock);
+
+ return kIOReturnSuccess;
}
+IOInterruptController *
+IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
+{
+ OSObject *object;
+
+ IOLockLock(gIOInterruptControllersLock);
+ while (1) {
+ object = gIOInterruptControllers->getObject(name);
+
+ if (object != NULL) {
+ break;
+ }
+
+ IOLockSleep(gIOInterruptControllersLock,
+ gIOInterruptControllers, THREAD_UNINT);
+ }
-void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
+ IOLockUnlock(gIOInterruptControllersLock);
+ return OSDynamicCast(IOInterruptController, object);
+}
+
+
+void
+IOPlatformExpert::setCPUInterruptProperties(IOService *service)
{
- IOCPUInterruptController *controller;
-
- controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
- if (controller) controller->setCPUInterruptProperties(service);
+ IOCPUInterruptController *controller;
+
+ controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
+ if (controller) {
+ controller->setCPUInterruptProperties(service);
+ }
}
-bool IOPlatformExpert::atInterruptLevel(void)
+bool
+IOPlatformExpert::atInterruptLevel(void)
{
- return ml_at_interrupt_context();
+ return ml_at_interrupt_context();
}
-bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
+bool
+IOPlatformExpert::platformAdjustService(IOService */*service*/)
{
- return true;
+ return true;
+}
+
+void
+IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs)
+{
+ *secs = getGMTTimeOfDay();
+ *nsecs = 0;
+}
+
+void
+IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs)
+{
+ setGMTTimeOfDay(secs);
}
//
//*********************************************************************************
-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
}
//
// 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);
}
// 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 );
}
//*********************************************************************************
//
//*********************************************************************************
-bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
+bool
+IOPlatformExpert::hasPMFeature(unsigned long featureMask)
{
- return ((_pePMFeatures & featureMask) != 0);
+ return (_pePMFeatures & featureMask) != 0;
}
//*********************************************************************************
//
//*********************************************************************************
-bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
+bool
+IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask)
{
- return ((_pePrivPMFeatures & privFeatureMask) != 0);
+ return (_pePrivPMFeatures & privFeatureMask) != 0;
}
//*********************************************************************************
//
//*********************************************************************************
-int IOPlatformExpert::numBatteriesSupported (void)
+int
+IOPlatformExpert::numBatteriesSupported(void)
{
- return (_peNumBatteriesSupported);
+ return _peNumBatteriesSupported;
}
//*********************************************************************************
// 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;
}
//*********************************************************************************
// 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;
}
//*********************************************************************************
//
// 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)
-{
- int type = (int)(long)p0;
+#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");
+
+#else /* ! CONFIG_EMBEDDED */
+ 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;
}
-
-long PEGetGMTTimeOfDay(void)
+boolean_t
+PEWriteNVRAMProperty(const char *symbol, const void *value,
+ const unsigned int len)
{
- long result = 0;
-
- if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay();
-
- return (result);
+ return PEWriteNVRAMPropertyInternal(symbol, FALSE, value, len);
}
-void PESetGMTTimeOfDay(long secs)
+boolean_t
+PEWriteNVRAMPropertyWithCopy(const char *symbol, const void *value,
+ const unsigned int len)
{
- if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs);
+ return PEWriteNVRAMPropertyInternal(symbol, TRUE, value, len);
}
-} /* extern "C" */
+boolean_t
+PERemoveNVRAMProperty(const char *symbol)
+{
+ const OSSymbol *sym;
-void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
-{
- OSData * data;
- IORegistryEntry * entry;
- OSString * string = 0;
- uuid_string_t uuid;
-
- 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( );
- }
-
- 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;
-}
+ if (!symbol) {
+ goto err;
+ }
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ if (init_gIOOptionsEntry() < 0) {
+ goto err;
+ }
-#undef super
-#define super IOPlatformExpert
+ sym = OSSymbol::withCStringNoCopy(symbol);
+ if (!sym) {
+ goto err;
+ }
-OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
+ gIOOptionsEntry->removeProperty(sym);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
+ sym->release();
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ gIOOptionsEntry->sync();
+ return TRUE;
+
+err:
+ return FALSE;
+}
-IOService * IODTPlatformExpert::probe( IOService * provider,
- SInt32 * score )
+long
+PEGetGMTTimeOfDay(void)
{
- if( !super::probe( provider, score))
- return( 0 );
+ clock_sec_t secs;
+ clock_usec_t usecs;
- // check machine types
- if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
- return( 0 );
+ PEGetUTCTimeOfDay(&secs, &usecs);
+ return secs;
+}
- return( this);
+void
+PESetGMTTimeOfDay(long secs)
+{
+ PESetUTCTimeOfDay(secs, 0);
}
-bool IODTPlatformExpert::configure( IOService * provider )
+void
+PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs)
{
- if( !super::configure( provider))
- return( false);
+ clock_nsec_t nsecs = 0;
+
+ *secs = 0;
+ if (gIOPlatform) {
+ gIOPlatform->getUTCTimeOfDay(secs, &nsecs);
+ }
- processTopLevel( provider );
+ assert(nsecs < NSEC_PER_SEC);
+ *usecs = nsecs / NSEC_PER_USEC;
+}
- return( true );
+void
+PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs)
+{
+ assert(usecs < USEC_PER_SEC);
+ if (gIOPlatform) {
+ gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC);
+ }
}
-IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
+coprocessor_type_t
+PEGetCoprocessorVersion( void )
{
- IOService * nub;
+ coprocessor_type_t coprocessor_version = kCoprocessorVersionNone;
+#if !CONFIG_EMBEDDED
+ IORegistryEntry *platform_entry = NULL;
+ OSData *coprocessor_version_obj = NULL;
- nub = new IOPlatformDevice;
- if( nub) {
- if( !nub->init( from, gIODTPlane )) {
- nub->free();
- nub = 0;
+ 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();
}
- }
- return( nub);
+#endif
+ return coprocessor_version;
}
+} /* extern "C" */
-bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
+void
+IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
{
- IORegistryEntry * next;
- IOService * nub;
- bool ok = true;
+ 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();
+ }
+#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 };
- if( iter) {
- while( (next = (IORegistryEntry *) iter->getNextObject())) {
+ SHA1Init( &context );
+ SHA1Update( &context, space, sizeof(space));
+ SHA1Update( &context, data->getBytesNoCopy(), data->getLength());
+ SHA1Final( digest, &context );
- if( 0 == (nub = createNub( next )))
- continue;
+ digest[6] = (digest[6] & 0x0F) | 0x50;
+ digest[8] = (digest[8] & 0x3F) | 0x80;
- nub->attach( parent );
- nub->registerService();
- }
- iter->release();
- }
+ uuid_unparse( digest, uuid );
+ string = OSString::withCString( uuid );
+ }
- return( ok );
+ 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");
}
-void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
+IOReturn
+IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
+ bool waitForFunction,
+ void *param1, void *param2,
+ void *param3, void *param4)
{
- OSIterator * kids;
- IORegistryEntry * next;
- IORegistryEntry * cpus;
- IORegistryEntry * options;
+ IOService *service, *_resources;
- // infanticide
- kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
- if( kids) {
- while( (next = (IORegistryEntry *)kids->getNextObject())) {
- next->detachAll( gIODTPlane);
+ 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());
+ }
}
- 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();
+ if (waitForFunction) {
+ _resources = waitForService(resourceMatching(functionName));
+ } else {
+ _resources = getResourceService();
+ }
+ if (_resources == NULL) {
+ return kIOReturnUnsupported;
}
- }
- }
- // Publish the cpus.
- cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
- if ( cpus)
- createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
+ service = OSDynamicCast(IOService, _resources->getProperty(functionName));
+ if (service == NULL) {
+ return kIOReturnUnsupported;
+ }
- // publish top level, minus excludeList
- createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
+ return service->callPlatformFunction(functionName, waitForFunction,
+ param1, param2, param3, param4);
}
-IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
+IOByteCount
+IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
{
- if( nub->getDeviceMemory())
- return( kIOReturnSuccess );
+ return 0;
+}
- IODTResolveAddressing( nub, "reg", 0);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- return( kIOReturnSuccess);
+#undef super
+#define super IOPlatformExpert
+
+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);
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+IOService *
+IODTPlatformExpert::probe( IOService * provider,
+ SInt32 * score )
+{
+ if (!super::probe( provider, score)) {
+ return NULL;
+ }
+
+ // check machine types
+ if (!provider->compareNames( getProperty( gIONameMatchKey ))) {
+ return NULL;
+ }
+
+ return this;
}
-bool IODTPlatformExpert::compareNubName( const IOService * nub,
- OSString * name, OSString ** matched ) const
+bool
+IODTPlatformExpert::configure( IOService * provider )
{
- return( IODTCompareNubName( nub, name, matched )
- || super::compareNubName( nub, name, matched) );
+ if (!super::configure( provider)) {
+ return false;
+ }
+
+ processTopLevel( provider );
+
+ return true;
}
-bool IODTPlatformExpert::getModelName( char * name, int maxLength )
+IOService *
+IODTPlatformExpert::createNub( IORegistryEntry * from )
{
- OSData * prop;
- const char * str;
- int len;
- char c;
- bool ok = false;
+ IOService * nub;
+
+ nub = new IOPlatformDevice;
+ if (nub) {
+ if (!nub->init( from, gIODTPlane )) {
+ nub->free();
+ nub = NULL;
+ }
+ }
+ return nub;
+}
- maxLength--;
+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;
+}
- prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
- if( prop ) {
- str = (const char *) prop->getBytesNoCopy();
+void
+IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
+{
+ OSIterator * kids;
+ IORegistryEntry * next;
+ IORegistryEntry * cpus;
+ IORegistryEntry * options;
- if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
- str += strlen( "AAPL," );
+ // infanticide
+ kids = IODTFindMatchingEntries( rootEntry, 0, deleteList());
+ if (kids) {
+ while ((next = (IORegistryEntry *)kids->getNextObject())) {
+ next->detachAll( gIODTPlane);
+ }
+ kids->release();
+ }
- len = 0;
- while( (c = *str++)) {
- if( (c == '/') || (c == ' '))
- c = '-';
+ // 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();
+ }
+ }
+ }
- name[ len++ ] = c;
- if( len >= maxLength)
- break;
+ // Publish the cpus.
+ cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
+ if (cpus) {
+ createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, NULL));
+ cpus->release();
}
- name[ len ] = 0;
- ok = true;
- }
- return( ok );
+ // publish top level, minus excludeList
+ createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
}
-bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
+IOReturn
+IODTPlatformExpert::getNubResources( IOService * nub )
{
- OSData * prop;
- bool ok = false;
+ if (nub->getDeviceMemory()) {
+ return kIOReturnSuccess;
+ }
- maxLength--;
- prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
- ok = (0 != prop);
+ IODTResolveAddressing( nub, "reg", NULL);
- if( ok )
- strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+ return kIOReturnSuccess;
+}
+
+bool
+IODTPlatformExpert::compareNubName( const IOService * nub,
+ OSString * name, OSString ** matched ) const
+{
+ return IODTCompareNubName( nub, name, matched )
+ || super::compareNubName( nub, name, matched);
+}
- return( ok );
+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;
+ }
+ return ok;
+}
+
+bool
+IODTPlatformExpert::getMachineName( char * name, int maxLength )
+{
+ OSData * prop;
+ bool ok = false;
+
+ maxLength--;
+ prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
+ ok = (NULL != prop);
+
+ if (ok) {
+ strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+ }
+
+ 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;
}
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();
+ }
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 );
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
*********************************************************************/
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;
}
-