X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/060df5ea7c632b1ac8cc8aac1fb59758165c2084..c7d2c2c6ee645e10cbccdd01c6191873ec77239d:/iokit/Kernel/IOPlatformExpert.cpp diff --git a/iokit/Kernel/IOPlatformExpert.cpp b/iokit/Kernel/IOPlatformExpert.cpp index f00ffd725..31ab8b700 100644 --- a/iokit/Kernel/IOPlatformExpert.cpp +++ b/iokit/Kernel/IOPlatformExpert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008 Apple Inc. All rights reserved. + * Copyright (c) 1998-2014 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -39,11 +39,13 @@ #include #include #include +#include #include #include #include +#include extern "C" { #include @@ -61,11 +63,11 @@ static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen) OSDefineMetaClassAndStructors(IOPlatformExpert, IOService) OSMetaClassDefineReservedUsed(IOPlatformExpert, 0); - OSMetaClassDefineReservedUsed(IOPlatformExpert, 1); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 2); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 3); -OSMetaClassDefineReservedUnused(IOPlatformExpert, 4); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 2); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 3); +OSMetaClassDefineReservedUsed(IOPlatformExpert, 4); + OSMetaClassDefineReservedUnused(IOPlatformExpert, 5); OSMetaClassDefineReservedUnused(IOPlatformExpert, 6); OSMetaClassDefineReservedUnused(IOPlatformExpert, 7); @@ -77,6 +79,7 @@ OSMetaClassDefineReservedUnused(IOPlatformExpert, 11); static IOPlatformExpert * gIOPlatform; static OSDictionary * gIOInterruptControllers; static IOLock * gIOInterruptControllersLock; +static IODTNVRAM *gIOOptionsEntry; OSSymbol * gPlatformInterruptControllerName; @@ -103,7 +106,9 @@ bool IOPlatformExpert::start( IOService * provider ) // 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); + // Register the presence or lack thereof a system // PCI address mapper with the IOMapper class IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey)); @@ -258,7 +263,7 @@ int IOPlatformExpert::haltRestart(unsigned int type) // On ARM kPEPanicRestartCPU is supported in the drivers if (type == kPEPanicRestartCPU) type = kPERestartCPU; - + if (PE_halt_restart) return (*PE_halt_restart)(type); else return -1; } @@ -320,6 +325,17 @@ IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterru return kIOReturnSuccess; } +IOReturn IOPlatformExpert::deregisterInterruptController(OSSymbol *name) +{ + IOLockLock(gIOInterruptControllersLock); + + gIOInterruptControllers->removeObject(name); + + IOLockUnlock(gIOInterruptControllersLock); + + return kIOReturnSuccess; +} + IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name) { OSObject *object; @@ -359,6 +375,17 @@ bool IOPlatformExpert::platformAdjustService(IOService */*service*/) 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); +} + //********************************************************************************* // PMLog @@ -369,43 +396,14 @@ void IOPlatformExpert:: PMLog(const char *who, unsigned long event, unsigned long param1, unsigned long param2) { - UInt32 debugFlags = gIOKitDebug; - UInt32 traceFlags = gIOKitTrace; - - 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; - } - - // Record the timestamp, wish I had a this pointer - IOTimeStampConstant(code, (uintptr_t) who, 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 } @@ -779,12 +777,16 @@ int PEGetPlatformEpoch(void) int PEHaltRestart(unsigned int type) { - IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain(); + IOPMrootDomain *pmRootDomain; AbsoluteTime deadline; thread_call_t shutdown_hang; + IORegistryEntry *node; + OSData *data; + uint32_t timeout = 30; 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() @@ -792,11 +794,20 @@ int PEHaltRestart(unsigned int type) /* Spawn a thread that will panic in 30 seconds. If all goes well the machine will be off by the time - the timer expires. + the timer expires. If the device wants a different + timeout, use that value instead of 30 seconds. */ +#define RESTART_NODE_PATH "/chosen" + 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()); + } + shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut, - (thread_call_param_t) type); - clock_interval_to_deadline( 30, kSecondScale, &deadline ); + (thread_call_param_t)(uintptr_t) type); + clock_interval_to_deadline( timeout, kSecondScale, &deadline ); thread_call_enter1_delayed( shutdown_hang, 0, deadline ); pmRootDomain->handlePlatformHaltRestart(type); @@ -809,6 +820,10 @@ int PEHaltRestart(unsigned int type) replies. */ } + else if(type == kPEPanicRestartCPU || type == kPEPanicSync) + { + IOCPURunPlatformPanicActions(type); + } if (gIOPlatform) return gIOPlatform->haltRestart(type); else return -1; @@ -820,18 +835,204 @@ UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length) else return 0; } -long PEGetGMTTimeOfDay(void) + + +inline static int init_gIOOptionsEntry(void) +{ + IORegistryEntry *entry; + void *nvram_entry; + volatile void **options; + int ret = -1; + + if (gIOOptionsEntry) + return 0; + + entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); + if (!entry) + return -1; + + 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; + } + + return 0; + +release: + 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) +{ + OSObject *obj; + OSData *data; + unsigned int vlen; + + if (!symbol || !len) + goto err; + + if (init_gIOOptionsEntry() < 0) + goto err; + + vlen = *len; + *len = 0; + + obj = gIOOptionsEntry->getProperty(symbol); + if (!obj) + goto err; + + /* convert to data */ + data = OSDynamicCast(OSData, obj); + if (!data) + goto err; + + *len = data->getLength(); + vlen = min(vlen, *len); + if (value && vlen) + memcpy((void *) value, data->getBytesNoCopy(), vlen); + + return TRUE; + +err: + 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) { - long result = 0; + const OSSymbol *sym; + OSData *data; + bool ret = false; + + if (!symbol || !value || !len) + goto err; + + if (init_gIOOptionsEntry() < 0) + goto err; + + sym = OSSymbol::withCStringNoCopy(symbol); + if (!sym) + goto err; + + data = OSData::withBytes((void *) value, len); + if (!data) + goto sym_done; + + ret = gIOOptionsEntry->setProperty(sym, data); + data->release(); + +sym_done: + sym->release(); + + if (ret == true) { + gIOOptionsEntry->sync(); + return TRUE; + } + +err: + return FALSE; +} + + +boolean_t PERemoveNVRAMProperty(const char *symbol) +{ + const OSSymbol *sym; + + 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; - if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay(); +err: + return FALSE; - return (result); +} + +long PEGetGMTTimeOfDay(void) +{ + clock_sec_t secs; + clock_usec_t usecs; + + PEGetUTCTimeOfDay(&secs, &usecs); + return secs; } void PESetGMTTimeOfDay(long secs) { - if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(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); } } /* extern "C" */ @@ -1024,6 +1225,7 @@ void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry ) } else { dtNVRAM->attach(this); dtNVRAM->registerService(); + options->release(); } } } @@ -1031,7 +1233,10 @@ void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry ) // Publish the cpus. cpus = rootEntry->childFromPath( "cpus", gIODTPlane); if ( cpus) + { createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0)); + cpus->release(); + } // publish top level, minus excludeList createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList())); @@ -1241,7 +1446,6 @@ IOPlatformExpertDevice::initWithArgs( 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 @@ -1253,17 +1457,11 @@ IOPlatformExpertDevice::initWithArgs( if( !ok) return( false); + reserved = NULL; workLoop = IOWorkLoop::workLoop(); if (!workLoop) return false; - argsData[ 0 ] = dtTop; - argsData[ 1 ] = p2; - argsData[ 2 ] = p3; - argsData[ 3 ] = p4; - - setProperty("IOPlatformArgs", (void *)argsData, sizeof(argsData)); - return( true); } @@ -1319,6 +1517,40 @@ IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties ) return kIOReturnUnsupported; } +IOReturn IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + IOUserClient ** handler ) +{ + IOReturn err = kIOReturnSuccess; + IOUserClient * newConnect = 0; + IOUserClient * theConnect = 0; + + switch (type) + { + case kIOKitDiagnosticsClientType: + newConnect = IOKitDiagnosticsClient::withTask(owningTask); + if (!newConnect) err = kIOReturnNotPermitted; + break; + default: + err = kIOReturnBadArgument; + } + + if (newConnect) + { + if ((false == newConnect->attach(this)) + || (false == newConnect->start(this))) + { + newConnect->detach( this ); + newConnect->release(); + } + else + theConnect = newConnect; + } + + *handler = theConnect; + return (err); +} + void IOPlatformExpertDevice::free() { if (workLoop) @@ -1369,7 +1601,7 @@ class IOPanicPlatform : IOPlatformExpert { OSDeclareDefaultStructors(IOPanicPlatform); public: - bool start(IOService * provider); + bool start(IOService * provider) APPLE_KEXT_OVERRIDE; };