]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPlatformExpert.cpp
xnu-3248.30.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
index 03779d4b104d050e8f315f8da7cf026bd0b6e8c4..31ab8b7007f457778c98580577fb745fac7e3ca3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -39,6 +39,7 @@
 #include <IOKit/IOKitKeys.h>
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/IOUserClient.h>
+#include <IOKit/IOKitDiagnosticsUserClient.h>
 
 #include <IOKit/system.h>
 
@@ -62,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);
@@ -105,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));
@@ -322,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;
@@ -361,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
@@ -371,48 +396,14 @@ void IOPlatformExpert::
 PMLog(const char *who, unsigned long event,
       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
 }
 
 
@@ -747,16 +738,10 @@ 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;
 
     /* 30 seconds has elapsed - resume shutdown */
     if(gIOPlatform) gIOPlatform->haltRestart(type);
-#endif /* CONFIG_EMBEDDED */
 }
 
 
@@ -795,6 +780,9 @@ int PEHaltRestart(unsigned int type)
   IOPMrootDomain    *pmRootDomain;
   AbsoluteTime      deadline;
   thread_call_t     shutdown_hang;
+  IORegistryEntry   *node;
+  OSData            *data;
+  uint32_t          timeout = 30;
   
   if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU)
   {
@@ -806,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); 
@@ -823,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;
@@ -896,7 +897,7 @@ boolean_t PEReadNVRAMProperty(const char *symbol, void *value,
 
     *len  = data->getLength();
     vlen  = min(vlen, *len);
-    if (vlen)
+    if (value && vlen)
         memcpy((void *) value, data->getBytesNoCopy(), vlen);
 
     return TRUE;
@@ -905,6 +906,38 @@ 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)
@@ -943,18 +976,63 @@ err:
 }
 
 
-long PEGetGMTTimeOfDay(void)
+boolean_t PERemoveNVRAMProperty(const char *symbol)
 {
-       long    result = 0;
+    const OSSymbol *sym;
+
+    if (!symbol)
+        goto err;
+
+    if (init_gIOOptionsEntry() < 0)
+        goto err;
+
+    sym = OSSymbol::withCStringNoCopy(symbol);
+    if (!sym)
+        goto err;
 
-       if( gIOPlatform)                result = gIOPlatform->getGMTTimeOfDay();
+    gIOOptionsEntry->removeProperty(sym);
+
+    sym->release();
+
+    gIOOptionsEntry->sync();
+    return TRUE;
+
+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" */
@@ -966,41 +1044,6 @@ void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
     OSString *        string = 0;
     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 )
     {
@@ -1025,7 +1068,6 @@ void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
 
         entry->release( );
     }
-#endif /* !CONFIG_EMBEDDED */
 
     if ( string == 0 )
     {
@@ -1183,6 +1225,7 @@ void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
         } else {
          dtNVRAM->attach(this);
          dtNVRAM->registerService();
+         options->release();
        }
       }
     }
@@ -1190,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()));
@@ -1400,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
@@ -1412,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);
 }
 
@@ -1478,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)
@@ -1528,7 +1601,7 @@ class IOPanicPlatform : IOPlatformExpert {
     OSDeclareDefaultStructors(IOPanicPlatform);
 
 public:
-    bool start(IOService * provider);
+    bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
 };