]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPlatformExpert.cpp
xnu-2050.24.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
index 1b53461ecd5b7cf14fb2f7522f1236d0a8be6a86..29c286ea64f52d01e1487ed952e9dea009dd8231 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -25,9 +25,6 @@
  * 
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
-/*
- * HISTORY
- */
  
 #include <IOKit/IOCPU.h>
 #include <IOKit/IODeviceTreeSupport.h>
@@ -47,6 +44,7 @@
 
 #include <libkern/c++/OSContainers.h>
 #include <libkern/crypto/sha1.h>
+#include <libkern/OSAtomic.h>
 
 extern "C" {
 #include <machine/machine_routines.h>
@@ -54,9 +52,6 @@ extern "C" {
 #include <uuid/uuid.h>
 }
 
-/* Delay period for UPS halt */
-#define kUPSDelayHaltCPU_msec   (1000*60*5)
-
 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
 static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen);
 
@@ -83,6 +78,7 @@ OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
 static IOPlatformExpert * gIOPlatform;
 static OSDictionary * gIOInterruptControllers;
 static IOLock * gIOInterruptControllersLock;
+static IODTNVRAM *gIOOptionsEntry;
 
 OSSymbol * gPlatformInterruptControllerName;
 
@@ -107,9 +103,11 @@ bool IOPlatformExpert::start( IOService * provider )
       return false;
     
     // Override the mapper present flag is requested by boot arguments.
-    if (PE_parse_boot_arg("dart", &debugFlags) && (debugFlags == 0))
+    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));
@@ -254,22 +252,17 @@ int IOPlatformExpert::haltRestart(unsigned int type)
 {
   if (type == kPEPanicSync) return 0;
 
-  if (type == kPEHangCPU) while (1);
+  if (type == kPEHangCPU) while (true) {}
 
   if (type == kPEUPSDelayHaltCPU) {
-    // Stall shutdown for 5 minutes, and if no outside force has 
-    // removed our power at that point, proceed with a reboot.
-    IOSleep( kUPSDelayHaltCPU_msec );
-
-    // Ideally we never reach this point.
-
-    type = kPERestartCPU;
+    // RestartOnPowerLoss feature was turned on, proceed with shutdown.
+    type = kPEHaltCPU;
   }
 
   // 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;
 }
@@ -380,41 +373,14 @@ void IOPlatformExpert::
 PMLog(const char *who, unsigned long event,
       unsigned long param1, unsigned long param2)
 {
-    UInt32 debugFlags = gIOKitDebug;
-
-    if (debugFlags & kIOLogPower) {
-
-       uint32_t nows, nowus;
+       clock_sec_t nows;
+       clock_usec_t nowus;
        clock_get_system_microtime(&nows, &nowus);
        nowus += (nows % 1000) * 1000000;
 
-        kprintf("pm%u %x %.30s %d %x %x\n",
-               nowus, (unsigned) current_thread(), who,        // Identity
-               (int) event, param1, param2);                   // Args
-
-       if (debugFlags & kIOLogTracePower) {
-           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, (UInt32) who, event, param1, param2);
-       }
-    }
+    kprintf("pm%u %p %.30s %d %lx %lx\n",
+               nowus, current_thread(), who,   // Identity
+               (int) event, (long) param1, (long) param2);                     // Args
 }
 
 
@@ -433,7 +399,6 @@ void IOPlatformExpert::PMInstantiatePowerDomains ( void )
     root->init();
     root->attach(this);
     root->start(this);
-    root->youAreRoot();
 }
 
 
@@ -750,10 +715,16 @@ static void IOShutdownNotificationsTimedOut(
     thread_call_param_t p0, 
     thread_call_param_t p1)
 {
-    int type = (int)p0;
+#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 */
 }
 
 
@@ -789,13 +760,13 @@ int PEGetPlatformEpoch(void)
 
 int PEHaltRestart(unsigned int type)
 {
-  IOPMrootDomain    *pmRootDomain = IOService::getPMRootDomain();
+  IOPMrootDomain    *pmRootDomain;
   AbsoluteTime      deadline;
   thread_call_t     shutdown_hang;
-  unsigned int      tell_type;
   
   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()
@@ -809,15 +780,8 @@ int PEHaltRestart(unsigned int type)
                         (thread_call_param_t) type);
     clock_interval_to_deadline( 30, kSecondScale, &deadline );
     thread_call_enter1_delayed( shutdown_hang, 0, deadline );
-    
-
-    if( kPEUPSDelayHaltCPU == type ) {
-        tell_type = kPEHaltCPU;
-    } else {
-        tell_type = type;
-    }
 
-    pmRootDomain->handlePlatformHaltRestart(tell_type); 
+    pmRootDomain->handlePlatformHaltRestart(type); 
     /* This notification should have few clients who all do 
        their work synchronously.
              
@@ -838,20 +802,127 @@ UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
   else return 0;
 }
 
+
+
+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 (vlen)
+        memcpy((void *) value, data->getBytesNoCopy(), vlen);
+
+    return TRUE;
+
+err:
+    return FALSE;
+}
+
+
+boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value, 
+                               const unsigned int len)
+{
+    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;
+}
+
+
 long PEGetGMTTimeOfDay(void)
 {
        long    result = 0;
 
-    if( gIOPlatform)
-               result = gIOPlatform->getGMTTimeOfDay();
+       if( gIOPlatform)                result = gIOPlatform->getGMTTimeOfDay();
 
        return (result);
 }
 
 void PESetGMTTimeOfDay(long secs)
 {
-    if( gIOPlatform)
-               gIOPlatform->setGMTTimeOfDay(secs);
+    if( gIOPlatform)           gIOPlatform->setGMTTimeOfDay(secs);
 }
 
 } /* extern "C" */
@@ -861,8 +932,43 @@ void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
     OSData *          data;
     IORegistryEntry * entry;
     OSString *        string = 0;
-    char              uuid[ 36 + 1 ];
+    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 )
     {
@@ -887,6 +993,7 @@ void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
 
         entry->release( );
     }
+#endif /* !CONFIG_EMBEDDED */
 
     if ( string == 0 )
     {
@@ -925,7 +1032,7 @@ IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
   if (waitForFunction) {
     _resources = waitForService(resourceMatching(functionName));
   } else {
-    _resources = resources();
+    _resources = getResourceService();
   }
   if (_resources == 0) return kIOReturnUnsupported;
   
@@ -1406,3 +1513,4 @@ bool IOPanicPlatform::start(IOService * provider) {
 
     return false;
 }
+