]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPlatformExpert.cpp
xnu-6153.61.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
index bc3c0e52734c411ccea76e4d2f553ce9c7dc5580..1fb74c64288dfdadcd17eeac6ed90a2e9c4019f2 100644 (file)
@@ -1,17 +1,20 @@
 /*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
- * 
  * 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
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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_LICENSE_HEADER_END@
- */
-/*
- * HISTORY
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
+
 #include <IOKit/IOCPU.h>
 #include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/IOKitDebug.h>
 #include <IOKit/IORangeAllocator.h>
 #include <IOKit/IOWorkLoop.h>
 #include <IOKit/pwr_mgt/RootDomain.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 <libkern/OSAtomic.h>
 
 extern "C" {
 #include <machine/machine_routines.h>
 #include <pexpert/pexpert.h>
+#include <uuid/uuid.h>
 }
 
-void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
-static void getCStringForObject (OSObject * inObj, char * outStr);
+#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;
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -56,285 +83,393 @@ static void getCStringForObject (OSObject * inObj, char * outStr);
 
 OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
 
-OSMetaClassDefineReservedUsed(IOPlatformExpert,  0);
-
-OSMetaClassDefineReservedUnused(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);
 
 static IOPlatformExpert * gIOPlatform;
 static OSDictionary * gIOInterruptControllers;
 static IOLock * gIOInterruptControllersLock;
+static IODTNVRAM *gIOOptionsEntry;
 
 OSSymbol * gPlatformInterruptControllerName;
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-bool IOPlatformExpert::attach( IOService * provider )
+bool
+IOPlatformExpert::attach( IOService * provider )
 {
+       if (!super::attach( provider )) {
+               return false;
+       }
 
-    if( !super::attach( provider ))
-       return( false);
-
-    return( true);
+       return true;
 }
 
-bool IOPlatformExpert::start( IOService * provider )
+bool
+IOPlatformExpert::start( IOService * provider )
 {
-    IORangeAllocator * physicalRanges;
-    OSData *           busFrequency;
-    
-    if (!super::start(provider))
-      return false;
+       IORangeAllocator *  physicalRanges;
+       OSData *            busFrequency;
+       uint32_t            debugFlags;
 
-    // Register the presence or lack thereof a system 
-    // PCI address mapper with the IOMapper class
 
-#if 1
-    IORegistryEntry * regEntry = IORegistryEntry::fromPath("/u3/dart", gIODTPlane);
-    if (!regEntry)
-       regEntry = IORegistryEntry::fromPath("/dart", gIODTPlane);
-    if (regEntry) {
-       int debugFlags;
-       if (!PE_parse_boot_arg("dart", &debugFlags) || debugFlags)
-           setProperty(kIOPlatformMapperPresentKey, kOSBooleanTrue);
-       regEntry->release();
-    }
-#endif
+       if (!super::start(provider)) {
+               return false;
+       }
 
-    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();
-    
-    return( configure(provider) );
-}
+       // 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 */
+       }
 
-bool IOPlatformExpert::configure( IOService * provider )
-{
-    OSSet *            topLevel;
-    OSDictionary *     dict;
-    IOService *        nub;
+       // 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();
 
-    topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
+       // 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();
 
-    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();
-        }
-    }
+       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);
+}
+
+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 );
+       return true;
 }
 
-IOService * IOPlatformExpert::createNub( OSDictionary * from )
+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;
+}
+
+bool
+IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
 {
-  _peMachineType = peMachineType;
+       return false;
 }
 
-bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
+bool
+IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
 {
-    return( false );
+       return false;
 }
 
-bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
+OSString*
+IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
 {
-    return( false );
+       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 == kPEHangCPU) while (1);
-  
-  if (PE_halt_restart) return (*PE_halt_restart)(type);
-  else return -1;
+       if (type == kPEPanicSync) {
+               return 0;
+       }
+
+       if (type == kPEHangCPU) {
+               while (true) {
+               }
+       }
+
+       if (type == kPEUPSDelayHaltCPU) {
+               // RestartOnPowerLoss feature was turned on, proceed with shutdown.
+               type = kPEHaltCPU;
+       }
+
+#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;
+       }
 }
 
-void IOPlatformExpert::sleepKernel(void)
+void
+IOPlatformExpert::sleepKernel(void)
 {
 #if 0
-  long cnt;
-  boolean_t intState;
-  
-  intState = ml_set_interrupts_enabled(false);
-  
-  for (cnt = 0; cnt < 10000; cnt++) {
-    IODelay(1000);
-  }
-  
-  ml_set_interrupts_enabled(intState);
+       long cnt;
+       boolean_t intState;
+
+       intState = ml_set_interrupts_enabled(false);
+
+       for (cnt = 0; cnt < 10000; cnt++) {
+               IODelay(1000);
+       }
+
+       ml_set_interrupts_enabled(intState);
 #else
 //  PE_initialize_console(0, kPEDisableScreen);
-  
-  IOCPUSleepKernel();
-  
+
+       IOCPUSleepKernel();
+
 //  PE_initialize_console(0, kPEEnableScreen);
 #endif
 }
 
-long IOPlatformExpert::getGMTTimeOfDay(void)
+long
+IOPlatformExpert::getGMTTimeOfDay(void)
 {
-    return(0);
+       return 0;
 }
 
-void IOPlatformExpert::setGMTTimeOfDay(long secs)
+void
+IOPlatformExpert::setGMTTimeOfDay(long secs)
 {
 }
 
 
-IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
+IOReturn
+IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
+{
+       return PE_current_console( consoleInfo);
+}
+
+IOReturn
+IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
+    unsigned int op)
 {
-    return( PE_current_console( consoleInfo));
+       return PE_initialize_console( consoleInfo, op );
 }
 
-IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
-                                               unsigned int op)
+IOReturn
+IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
 {
-    return( PE_initialize_console( consoleInfo, op ));
+       IOLockLock(gIOInterruptControllersLock);
+
+       gIOInterruptControllers->setObject(name, interruptController);
+
+       IOLockWakeup(gIOInterruptControllersLock,
+           gIOInterruptControllers, /* one-thread */ false);
+
+       IOLockUnlock(gIOInterruptControllersLock);
+
+       return kIOReturnSuccess;
 }
 
-IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
+IOReturn
+IOPlatformExpert::deregisterInterruptController(OSSymbol *name)
 {
-  IOLockLock(gIOInterruptControllersLock);
-  
-  gIOInterruptControllers->setObject(name, interruptController);
-  
-  IOLockWakeup(gIOInterruptControllersLock,
-               gIOInterruptControllers, /* one-thread */ false);
+       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);
+       }
 
-  IOLockUnlock(gIOInterruptControllersLock);
-  
-  return kIOReturnSuccess;
+       IOLockUnlock(gIOInterruptControllersLock);
+       return OSDynamicCast(IOInterruptController, object);
 }
 
-IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
+
+void
+IOPlatformExpert::setCPUInterruptProperties(IOService *service)
 {
-  OSObject              *object;
-  
-  IOLockLock(gIOInterruptControllersLock);
-  while (1) {
-    
-    object = gIOInterruptControllers->getObject(name);
-    
-    if (object != 0)
-       break;
-    
-    IOLockSleep(gIOInterruptControllersLock,
-               gIOInterruptControllers, THREAD_UNINT);
-  }
-  
-  IOLockUnlock(gIOInterruptControllersLock);
-  return OSDynamicCast(IOInterruptController, object);
+       IOCPUInterruptController *controller;
+
+       controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
+       if (controller) {
+               controller->setCPUInterruptProperties(service);
+       }
 }
 
+bool
+IOPlatformExpert::atInterruptLevel(void)
+{
+       return ml_at_interrupt_context();
+}
 
-void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
+bool
+IOPlatformExpert::platformAdjustService(IOService */*service*/)
 {
-  IOCPUInterruptController *controller;
-  
-  controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
-  if (controller) controller->setCPUInterruptProperties(service);
+       return true;
 }
 
-bool IOPlatformExpert::atInterruptLevel(void)
+void
+IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs)
 {
-  return ml_at_interrupt_context();
+       *secs = getGMTTimeOfDay();
+       *nsecs = 0;
 }
 
-bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
+void
+IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs)
 {
-  return true;
+       setGMTTimeOfDay(secs);
 }
 
 
@@ -343,12 +478,19 @@ bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
 //
 //*********************************************************************************
 
-void IOPlatformExpert::PMLog(const char * who,unsigned long event,unsigned long param1, unsigned long param2)
+void
+IOPlatformExpert::
+PMLog(const char *who, unsigned long event,
+    unsigned long param1, unsigned long param2)
 {
-    if( gIOKitDebug & kIOLogPower) {
-        kprintf("%s %02d %08x %08x\n",who,event,param1,param2);
-//        IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
-    }
+       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, OBFUSCATE(current_thread()), who,            // Identity
+           (int) event, (long)OBFUSCATE(param1), (long)OBFUSCATE(param2));                     // Args
 }
 
 
@@ -357,17 +499,17 @@ void IOPlatformExpert::PMLog(const char * who,unsigned long event,unsigned long
 //
 // 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->youAreRoot();
+       root = new IOPMrootDomain;
+       root->init();
+       root->attach(this);
+       root->start(this);
 }
 
 
@@ -378,9 +520,10 @@ void IOPlatformExpert::PMInstantiatePowerDomains ( void )
 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
 //*********************************************************************************
 
-void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
+void
+IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
 {
-    root->addPowerChild ( theDevice );
+       root->addPowerChild( theDevice );
 }
 
 //*********************************************************************************
@@ -388,9 +531,10 @@ void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevic
 //
 //*********************************************************************************
 
-bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
+bool
+IOPlatformExpert::hasPMFeature(unsigned long featureMask)
 {
-  return ((_pePMFeatures & featureMask) != 0);
+       return (_pePMFeatures & featureMask) != 0;
 }
 
 //*********************************************************************************
@@ -398,9 +542,10 @@ bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
 //
 //*********************************************************************************
 
-bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
+bool
+IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask)
 {
-  return ((_pePrivPMFeatures & privFeatureMask) != 0);
+       return (_pePrivPMFeatures & privFeatureMask) != 0;
 }
 
 //*********************************************************************************
@@ -408,9 +553,10 @@ bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
 //
 //*********************************************************************************
 
-int IOPlatformExpert::numBatteriesSupported (void)
+int
+IOPlatformExpert::numBatteriesSupported(void)
 {
-  return (_peNumBatteriesSupported);
+       return _peNumBatteriesSupported;
 }
 
 //*********************************************************************************
@@ -424,387 +570,895 @@ int IOPlatformExpert::numBatteriesSupported (void)
 // registered for the given service.
 //*********************************************************************************
 
-bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
-{
-  unsigned int    i;
-  unsigned int    numPowerTreeNodes;
-  OSDictionary *  entry;
-  OSDictionary *  matchingDictionary;
-  OSDictionary *  providerDictionary;
-  OSDictionary *  deviceDictionary;
-  OSDictionary *  nubDictionary;
-  OSArray *       children;
-  bool            nodeFound            = false;
-  bool            continueSearch       = false;
-  bool            deviceMatch          = false;
-  bool            providerMatch        = false;
-  bool            multiParentMatch     = false;
+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 ( (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));
+               }
+
+               if (false == continueSearch) {
+                       break;
+               }
+       }
 
-  numPowerTreeNodes = inSubTree->getCount ();
+       return nodeFound;
+}
 
-  // iterate through the power tree to find a home for this device
+//*********************************************************************************
+// RegisterServiceInTree
+//
+// Register a device at the specified node of our power tree.
+//*********************************************************************************
 
-  for ( i = 0; i < numPowerTreeNodes; i++ ) {
+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;
+               }
+       }
 
-    entry =  (OSDictionary *) inSubTree->getObject (i);
+       return registered;
+}
 
-    matchingDictionary = (OSDictionary *) entry->getObject ("device");
-    providerDictionary = (OSDictionary *) entry->getObject ("provider");
+//*********************************************************************************
+// printDictionaryKeys
+//
+// Print the keys for the given dictionary and selected contents.
+//*********************************************************************************
+void
+printDictionaryKeys(OSDictionary * inDictionary, char * inMsg)
+{
+       OSCollectionIterator * mcoll = OSCollectionIterator::withCollection(inDictionary);
+       OSSymbol * mkey;
+       OSString * ioClass;
+       unsigned int i = 0;
 
-    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 ();
-      }
-    }
+       mcoll->reset();
 
-    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 ();
-      }
-    }
+       mkey = OSDynamicCast(OSSymbol, mcoll->getNextObject());
 
-    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;
-      }
-    }
+       while (mkey) {
+               // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
 
-    nodeFound = (deviceMatch && providerMatch && multiParentMatch);
+               // if this is the IOClass key, print it's contents
 
-    // if the power tree specifies a provider dictionary but theNub is
-    // NULL then we cannot match with this entry.
+               if (mkey->isEqualTo("IOClass")) {
+                       ioClass = (OSString *) inDictionary->getObject("IOClass");
+                       if (ioClass) {
+                               IOLog("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy());
+                       }
+               }
 
-    if ( theNub == NULL && providerDictionary != NULL )
-      nodeFound = false;
-  
-    // if this node is THE ONE...then register the device
+               // if this is an IOProviderClass key print it
 
-    if ( nodeFound ) {
-      if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
+               if (mkey->isEqualTo("IOProviderClass")) {
+                       ioClass = (OSString *) inDictionary->getObject("IOProviderClass");
+                       if (ioClass) {
+                               IOLog("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy());
+                       }
+               }
 
-        if ( kIOLogPower & gIOKitDebug)
-          IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
+               // also print IONameMatch keys
+               if (mkey->isEqualTo("IONameMatch")) {
+                       ioClass = (OSString *) inDictionary->getObject("IONameMatch");
+                       if (ioClass) {
+                               IOLog("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy());
+                       }
+               }
 
-       numInstancesRegistered++;
+               // also print IONameMatched keys
 
-       // determine if we need to search for additional nodes for this item
-       multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
-      }
-      else
-       nodeFound = false;
-    }
+               if (mkey->isEqualTo("IONameMatched")) {
+                       ioClass = (OSString *) inDictionary->getObject("IONameMatched");
+                       if (ioClass) {
+                               IOLog("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy());
+                       }
+               }
 
-    continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
+#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 );
+                       }
+               }
+#endif
 
-    if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
-      nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
-      continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
-    }
+               // print name
 
-    if ( false == continueSearch )
-      break;
-  }
+               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);
+                       }
+               }
 
-  return ( nodeFound );
-}
+               mkey = (OSSymbol *) mcoll->getNextObject();
 
-//*********************************************************************************
-// RegisterServiceInTree
-//
-// Register a device at the specified node of our power tree.
-//*********************************************************************************
+               i++;
+       }
 
-bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
+       mcoll->release();
+}
+
+static void
+getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
 {
-  IOService *    aService;
-  bool           registered = false;
-  OSArray *      children;
-  unsigned int   numChildren;
-  OSDictionary * child;
+       char * buffer;
+       unsigned int    len, i;
 
-  // make sure someone is not already registered here
+       if ((NULL == inObj) || (NULL == outStr)) {
+               return;
+       }
 
-  if ( NULL == theTreeNode->getObject ("service") ) {
+       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;
+               }
+       }
+}
 
-    if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
+/* IOShutdownNotificationsTimedOut
+ * - Called from a timer installed by PEHaltRestart
+ */
+#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);
+               }
+       }
 
-      // 1. CHILDREN ------------------
+       /* 30 seconds has elapsed - resume shutdown */
+       if (gIOPlatform) {
+               gIOPlatform->haltRestart(type);
+       }
+#endif /* CONFIG_EMBEDDED */
+}
 
-      // 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);
-          }
-        }
-      }
+extern "C" {
+/*
+ * Callouts from BSD for machine name & model
+ */
+
+boolean_t
+PEGetMachineName( char * name, int maxLength )
+{
+       if (gIOPlatform) {
+               return gIOPlatform->getMachineName( name, maxLength );
+       } else {
+               return false;
+       }
+}
 
-      // 2. PARENT --------------------
+boolean_t
+PEGetModelName( char * name, int maxLength )
+{
+       if (gIOPlatform) {
+               return gIOPlatform->getModelName( name, maxLength );
+       } else {
+               return false;
+       }
+}
 
-      // also we must notify the parent of this node (if a registered service
-      // exists there) of a new child.
+int
+PEGetPlatformEpoch(void)
+{
+       if (gIOPlatform) {
+               return gIOPlatform->getBootROMType();
+       } else {
+               return -1;
+       }
+}
 
-      if ( theTreeParentNode ) {
-        if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
-          if (aService != theProvider)
-            aService->addPowerChild (theService);
-      }
+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
 
-      registered = true;
-    }
-  }
+               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);
+                       }
+               }
+       }
 
-  return registered;
+skip_to_haltRestart:
+       if (gIOPlatform) {
+               return gIOPlatform->haltRestart(type);
+       } else {
+               return -1;
+       }
 }
 
-//*********************************************************************************
-// printDictionaryKeys
-//
-// Print the keys for the given dictionary and selected contents.
-//*********************************************************************************
-void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
+UInt32
+PESavePanicInfo(UInt8 *buffer, UInt32 length)
 {
-  OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
-  OSSymbol * mkey;
-  OSString * ioClass;
-  unsigned int i = 0;
-  mcoll->reset ();
+       if (gIOPlatform != NULL) {
+               return gIOPlatform->savePanicInfo(buffer, length);
+       } else {
+               return 0;
+       }
+}
+
+void
+PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length)
+{
+       IOCPURunPlatformPanicSyncAction(buffer, offset, length);
+       return;
+}
 
-  mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
 
-  while (mkey) {
+inline static int
+init_gIOOptionsEntry(void)
+{
+       IORegistryEntry *entry;
+       void *nvram_entry;
+       volatile void **options;
+       int ret = -1;
 
-    // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
+       if (gIOOptionsEntry) {
+               return 0;
+       }
 
-    // if this is the IOClass key, print it's contents
+       entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+       if (!entry) {
+               return -1;
+       }
 
-    if ( mkey->isEqualTo ("IOClass") ) {
-      ioClass = (OSString *) inDictionary->getObject ("IOClass");
-      if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
-    }
+       nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
+       if (!nvram_entry) {
+               goto release;
+       }
 
-    // if this is an IOProviderClass key print it
+       options = (volatile void **) &gIOOptionsEntry;
+       if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
+               ret = 0;
+               goto release;
+       }
 
-    if ( mkey->isEqualTo ("IOProviderClass") ) {
-      ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
-      if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
+       return 0;
 
-    }
+release:
+       entry->release();
+       return ret;
+}
 
-    // also print IONameMatch keys
-    if ( mkey->isEqualTo ("IONameMatch") ) {
-      ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
-      if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
-    }
+/* 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;
 
-    // also print IONameMatched keys
+       if (!symbol || !len) {
+               goto err;
+       }
 
-    if ( mkey->isEqualTo ("IONameMatched") ) {
-      ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
-      if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
-    }
+       if (init_gIOOptionsEntry() < 0) {
+               goto err;
+       }
 
-#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 );
-    }
-#endif
+       vlen = *len;
+       *len = 0;
 
-    // print name
+       obj = gIOOptionsEntry->getProperty(symbol);
+       if (!obj) {
+               goto err;
+       }
 
-    if ( mkey->isEqualTo ("name") ) {
-      char nameStr[64];
-      nameStr[0] = 0;
-      getCStringForObject (inDictionary->getObject ("name"), nameStr );
-      if (strlen(nameStr) > 0)
-        IOLog ("%s name is %s\n", inMsg, nameStr);
-    }
+       /* convert to data */
+       data = OSDynamicCast(OSData, obj);
+       if (!data) {
+               goto err;
+       }
 
-    mkey = (OSSymbol *) mcoll->getNextObject ();
+       *len  = data->getLength();
+       vlen  = min(vlen, *len);
+       if (value && vlen) {
+               memcpy((void *) value, data->getBytesNoCopy(), vlen);
+       }
 
-    i++;
-  }
+       return TRUE;
 
-  mcoll->release ();
+err:
+       return FALSE;
 }
 
-static void getCStringForObject (OSObject * inObj, char * outStr)
+boolean_t
+PEWriteNVRAMBooleanProperty(const char *symbol, boolean_t value)
 {
-   char * buffer;
-   unsigned int    len, i;
+       const OSSymbol *sym = NULL;
+       OSBoolean *data = NULL;
+       bool ret = false;
 
-   if ( (NULL == inObj) || (NULL == outStr))
-     return;
+       if (symbol == NULL) {
+               goto exit;
+       }
 
-   char * objString = (char *) (inObj->getMetaClass())->getClassName();
+       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();
 
-   if ((0 == strcmp(objString,"OSString")) || (0 == strcmp (objString, "OSSymbol")))
-     strcpy (outStr, ((OSString *)inObj)->getCStringNoCopy());
+       /* success, force the NVRAM to flush writes */
+       if (ret == true) {
+               gIOOptionsEntry->sync();
+       }
 
-   else if (0 == strcmp(objString,"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;
-     }
-   }
+exit:
+       return ret;
 }
 
-/* IOPMPanicOnShutdownHang
- * - Called from a timer installed by PEHaltRestart
- */
-static void IOPMPanicOnShutdownHang(thread_call_param_t p0, thread_call_param_t p1)
+static boolean_t
+PEWriteNVRAMPropertyInternal(const char *symbol, boolean_t copySymbol, const void *value,
+    const unsigned int len)
 {
-    int type = (int)p0;
+       const OSSymbol *sym;
+       OSData *data;
+       bool ret = false;
 
-    /* 30 seconds has elapsed - resume shutdown */
-    gIOPlatform->haltRestart(type);
-}
+       if (!symbol || !value || !len) {
+               goto err;
+       }
 
+       if (init_gIOOptionsEntry() < 0) {
+               goto err;
+       }
 
-extern "C" {
+       if (copySymbol == TRUE) {
+               sym = OSSymbol::withCString(symbol);
+       } else {
+               sym = OSSymbol::withCStringNoCopy(symbol);
+       }
 
-/*
- * Callouts from BSD for machine name & model
- */ 
+       if (!sym) {
+               goto err;
+       }
+
+       data = OSData::withBytes((void *) value, len);
+       if (!data) {
+               goto sym_done;
+       }
+
+       ret = gIOOptionsEntry->setProperty(sym, data);
+       data->release();
 
-boolean_t PEGetMachineName( char * name, int maxLength )
+sym_done:
+       sym->release();
+
+       if (ret == true) {
+               gIOOptionsEntry->sync();
+               return TRUE;
+       }
+
+err:
+       return FALSE;
+}
+
+boolean_t
+PEWriteNVRAMProperty(const char *symbol, const void *value,
+    const unsigned int len)
 {
-    if( gIOPlatform)
-       return( gIOPlatform->getMachineName( name, maxLength ));
-    else
-       return( false );
+       return PEWriteNVRAMPropertyInternal(symbol, FALSE, value, len);
 }
 
-boolean_t PEGetModelName( char * name, int maxLength )
+boolean_t
+PEWriteNVRAMPropertyWithCopy(const char *symbol, const void *value,
+    const unsigned int len)
 {
-    if( gIOPlatform)
-       return( gIOPlatform->getModelName( name, maxLength ));
-    else
-       return( false );
+       return PEWriteNVRAMPropertyInternal(symbol, TRUE, value, len);
 }
 
-int PEGetPlatformEpoch(void)
+boolean_t
+PERemoveNVRAMProperty(const char *symbol)
 {
-    if( gIOPlatform)
-       return( gIOPlatform->getBootROMType());
-    else
-       return( -1 );
+       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;
+
+err:
+       return FALSE;
 }
 
-int PEHaltRestart(unsigned int type)
+long
+PEGetGMTTimeOfDay(void)
 {
-  IOPMrootDomain    *pmRootDomain = IOService::getPMRootDomain();
-  bool              noWaitForResponses;
-  AbsoluteTime      deadline;
-  thread_call_t     shutdown_hang;
-  
-  if(type == kPEHaltCPU || type == kPERestartCPU)
-  {
-    /* 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( &IOPMPanicOnShutdownHang, (thread_call_param_t) type);
-    clock_interval_to_deadline( 30, kSecondScale, &deadline );
-    thread_call_enter1_delayed( shutdown_hang, 0, deadline );
-    
-    noWaitForResponses = pmRootDomain->tellChangeDown2(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. In fact, it's a bad idea to even be calling
-       tellChangeDown2 from here at all.
-     */
-   }
+       clock_sec_t     secs;
+       clock_usec_t    usecs;
 
-  if (gIOPlatform) return gIOPlatform->haltRestart(type);
-  else return -1;
+       PEGetUTCTimeOfDay(&secs, &usecs);
+       return secs;
 }
 
-UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
+void
+PESetGMTTimeOfDay(long secs)
 {
-  if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
-  else return 0;
+       PESetUTCTimeOfDay(secs, 0);
 }
 
-long PEGetGMTTimeOfDay(void)
+void
+PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs)
 {
-    if( gIOPlatform)
-       return( gIOPlatform->getGMTTimeOfDay());
-    else
-       return( 0 );
+       clock_nsec_t    nsecs = 0;
+
+       *secs = 0;
+       if (gIOPlatform) {
+               gIOPlatform->getUTCTimeOfDay(secs, &nsecs);
+       }
+
+       assert(nsecs < NSEC_PER_SEC);
+       *usecs = nsecs / NSEC_PER_USEC;
 }
 
-void PESetGMTTimeOfDay(long secs)
+void
+PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs)
 {
-    if( gIOPlatform)
-       gIOPlatform->setGMTTimeOfDay(secs);
+       assert(usecs < USEC_PER_SEC);
+       if (gIOPlatform) {
+               gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC);
+       }
 }
 
+coprocessor_type_t
+PEGetCoprocessorVersion( void )
+{
+       coprocessor_type_t coprocessor_version = kCoprocessorVersionNone;
+#if !CONFIG_EMBEDDED
+       IORegistryEntry     *platform_entry = NULL;
+       OSData              *coprocessor_version_obj = NULL;
+
+       platform_entry = IORegistryEntry::fromPath(kIODeviceTreePlane ":/efi/platform");
+       if (platform_entry != NULL) {
+               coprocessor_version_obj = OSDynamicCast(OSData, platform_entry->getProperty("apple-coprocessor-version"));
+               if ((coprocessor_version_obj != NULL) && (coprocessor_version_obj->getLength() <= sizeof(uint64_t))) {
+                       memcpy(&coprocessor_version, coprocessor_version_obj->getBytesNoCopy(), coprocessor_version_obj->getLength());
+               }
+               platform_entry->release();
+       }
+#endif
+       return coprocessor_version;
+}
 } /* extern "C" */
 
-void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
+void
+IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
 {
-    publishResource("IONVRAM");
+       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 };
+
+                       SHA1Init( &context );
+                       SHA1Update( &context, space, sizeof(space));
+                       SHA1Update( &context, data->getBytesNoCopy(), data->getLength());
+                       SHA1Final( digest, &context );
+
+                       digest[6] = (digest[6] & 0x0F) | 0x50;
+                       digest[8] = (digest[8] & 0x3F) | 0x80;
+
+                       uuid_unparse( digest, uuid );
+                       string = OSString::withCString( uuid );
+               }
+
+               entry->release();
+       }
+#endif /* defined(XNU_TARGET_OS_OSX) */
+
+       if (string == NULL) {
+               entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+               if (entry) {
+                       data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ));
+                       if (data && data->getLength() == sizeof(uuid_t)) {
+                               uuid_unparse((uint8_t *) data->getBytesNoCopy(), uuid );
+                               string = OSString::withCString( uuid );
+                       }
+
+                       entry->release();
+               }
+       }
+
+       if (string) {
+               getProvider()->setProperty( kIOPlatformUUIDKey, string );
+               publishResource( kIOPlatformUUIDKey, string );
+
+               string->release();
+       }
+
+       publishResource("IONVRAM");
 }
 
-IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
-                                               bool waitForFunction,
-                                               void *param1, void *param2,
-                                               void *param3, void *param4)
+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 = resources();
-  }
-  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);
+       IOService *service, *_resources;
+
+       if (functionName == gIOPlatformQuiesceActionKey ||
+           functionName == gIOPlatformActiveActionKey) {
+               /*
+                * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction
+                * must consume that event themselves, without passing it up to super/IOPlatformExpert.
+                */
+               if (gEnforceQuiesceSafety) {
+                       panic("Class %s passed the quiesce/active action to IOPlatformExpert",
+                           getMetaClass()->getClassName());
+               }
+       }
+
+       if (waitForFunction) {
+               _resources = waitForService(resourceMatching(functionName));
+       } else {
+               _resources = getResourceService();
+       }
+       if (_resources == NULL) {
+               return kIOReturnUnsupported;
+       }
+
+       service = OSDynamicCast(IOService, _resources->getProperty(functionName));
+       if (service == NULL) {
+               return kIOReturnUnsupported;
+       }
+
+       return service->callPlatformFunction(functionName, waitForFunction,
+                  param1, param2, param3, param4);
 }
 
-IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
+IOByteCount
+IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
 {
-  return 0;
+       return 0;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -814,261 +1468,357 @@ IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
 
 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
 
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  0);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  1);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  2);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  3);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  4);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  5);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  6);
-OSMetaClassDefineReservedUnused(IODTPlatformExpert,  7);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
+OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-IOService * IODTPlatformExpert::probe( IOService * provider,
-                                       SInt32 * score )
+IOService *
+IODTPlatformExpert::probe( IOService * provider,
+    SInt32 * score )
 {
-    if( !super::probe( provider, score))
-       return( 0 );
+       if (!super::probe( provider, score)) {
+               return NULL;
+       }
 
-    // check machine types
-    if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
-        return( 0 );
+       // check machine types
+       if (!provider->compareNames( getProperty( gIONameMatchKey ))) {
+               return NULL;
+       }
 
-    return( this);
+       return this;
 }
 
-bool IODTPlatformExpert::configure( IOService * provider )
+bool
+IODTPlatformExpert::configure( IOService * provider )
 {
-    if( !super::configure( provider))
-       return( false);
+       if (!super::configure( provider)) {
+               return false;
+       }
 
-    processTopLevel( provider );
+       processTopLevel( provider );
 
-    return( true );
+       return true;
 }
 
-IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
+IOService *
+IODTPlatformExpert::createNub( IORegistryEntry * from )
 {
-    IOService *                nub;
+       IOService *         nub;
 
-    nub = new IOPlatformDevice;
-    if( nub) {
-       if( !nub->init( from, gIODTPlane )) {
-           nub->free();
-           nub = 0;
+       nub = new IOPlatformDevice;
+       if (nub) {
+               if (!nub->init( from, gIODTPlane )) {
+                       nub->free();
+                       nub = NULL;
+               }
        }
-    }
-    return( nub);
+       return nub;
 }
 
-bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
-{
-    IORegistryEntry *  next;
-    IOService *                nub;
-    bool               ok = true;
-
-    if( iter) {
-       while( (next = (IORegistryEntry *) iter->getNextObject())) {
-
-            if( 0 == (nub = createNub( next )))
-                continue;
-
-            nub->attach( parent );
-            nub->registerService();
-        }
-       iter->release();
-    }
+bool
+IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
+{
+       IORegistryEntry *   next;
+       IOService *         nub;
+       bool                ok = true;
+
+       if (iter) {
+               while ((next = (IORegistryEntry *) iter->getNextObject())) {
+                       if (NULL == (nub = createNub( next ))) {
+                               continue;
+                       }
+
+                       nub->attach( parent );
+                       nub->registerService();
+               }
+               iter->release();
+       }
 
-    return( ok );
+       return ok;
 }
 
-void IODTPlatformExpert::processTopLevel( IORegistryEntry * root )
+void
+IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
 {
-    OSIterator *       kids;
-    IORegistryEntry *  next;
-    IORegistryEntry *  cpus;
-    IORegistryEntry *  options;
+       OSIterator *        kids;
+       IORegistryEntry *   next;
+       IORegistryEntry *   cpus;
+       IORegistryEntry *   options;
 
-    // infanticide
-    kids = IODTFindMatchingEntries( root, 0, deleteList() );
-    if( kids) {
-       while( (next = (IORegistryEntry *)kids->getNextObject())) {
-           next->detachAll( gIODTPlane);
+       // infanticide
+       kids = IODTFindMatchingEntries( rootEntry, 0, deleteList());
+       if (kids) {
+               while ((next = (IORegistryEntry *)kids->getNextObject())) {
+                       next->detachAll( gIODTPlane);
+               }
+               kids->release();
        }
-       kids->release();
-    }
 
-    // Publish an IODTNVRAM class on /options.
-    options = root->childFromPath("options", gIODTPlane);
-    if (options) {
-      dtNVRAM = new IODTNVRAM;
-      if (dtNVRAM) {
-        if (!dtNVRAM->init(options, gIODTPlane)) {
-         dtNVRAM->release();
-         dtNVRAM = 0;
-        } else {
-         dtNVRAM->attach(this);
-         dtNVRAM->registerService();
+       // Publish an IODTNVRAM class on /options.
+       options = rootEntry->childFromPath("options", gIODTPlane);
+       if (options) {
+               dtNVRAM = new IODTNVRAM;
+               if (dtNVRAM) {
+                       if (!dtNVRAM->init(options, gIODTPlane)) {
+                               dtNVRAM->release();
+                               dtNVRAM = NULL;
+                       } else {
+                               dtNVRAM->attach(this);
+                               dtNVRAM->registerService();
+                               options->release();
+                       }
+               }
        }
-      }
-    }
 
-    // Publish the cpus.
-    cpus = root->childFromPath( "cpus", gIODTPlane);
-    if ( cpus)
-      createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
+       // Publish the cpus.
+       cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
+       if (cpus) {
+               createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, NULL));
+               cpus->release();
+       }
 
-    // publish top level, minus excludeList
-    createNubs( this, IODTFindMatchingEntries( root, kIODTExclusive, excludeList()));
+       // publish top level, minus excludeList
+       createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
 }
 
-IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
+IOReturn
+IODTPlatformExpert::getNubResources( IOService * nub )
 {
-  if( nub->getDeviceMemory())
-    return( kIOReturnSuccess );
+       if (nub->getDeviceMemory()) {
+               return kIOReturnSuccess;
+       }
 
-  IODTResolveAddressing( nub, "reg", 0);
+       IODTResolveAddressing( nub, "reg", NULL);
 
-  return( kIOReturnSuccess);
+       return kIOReturnSuccess;
 }
 
-bool IODTPlatformExpert::compareNubName( const IOService * nub,
-                               OSString * name, OSString ** matched ) const
+bool
+IODTPlatformExpert::compareNubName( const IOService * nub,
+    OSString * name, OSString ** matched ) const
 {
-    return( IODTCompareNubName( nub, name, matched )
-         || super::compareNubName( nub, name, matched) );
+       return IODTCompareNubName( nub, name, matched )
+              || super::compareNubName( nub, name, matched);
 }
 
-bool IODTPlatformExpert::getModelName( char * name, int maxLength )
-{
-    OSData *           prop;
-    const char *       str;
-    int                        len;
-    char               c;
-    bool               ok = false;
-
-    maxLength--;
-
-    prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
-    if( prop ) {
-       str = (const char *) prop->getBytesNoCopy();
-
-       if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
-           str += strlen( "AAPL," );
-
-       len = 0;
-       while( (c = *str++)) {
-           if( (c == '/') || (c == ' '))
-               c = '-';
-
-           name[ len++ ] = c;
-           if( len >= maxLength)
-               break;
+bool
+IODTPlatformExpert::getModelName( char * name, int maxLength )
+{
+       OSData *            prop;
+       const char *        str;
+       int                 len;
+       char                c;
+       bool                ok = false;
+
+       maxLength--;
+
+       prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
+       if (prop) {
+               str = (const char *) prop->getBytesNoCopy();
+
+               if (0 == strncmp( str, "AAPL,", strlen( "AAPL," ))) {
+                       str += strlen( "AAPL," );
+               }
+
+               len = 0;
+               while ((c = *str++)) {
+                       if ((c == '/') || (c == ' ')) {
+                               c = '-';
+                       }
+
+                       name[len++] = c;
+                       if (len >= maxLength) {
+                               break;
+                       }
+               }
+
+               name[len] = 0;
+               ok = true;
        }
-
-       name[ len ] = 0;
-       ok = true;
-    }
-    return( ok );
+       return ok;
 }
 
-bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
+bool
+IODTPlatformExpert::getMachineName( char * name, int maxLength )
 {
-    OSData *           prop;
-    bool               ok = false;
+       OSData *            prop;
+       bool                ok = false;
 
-    maxLength--;
-    prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
-    ok = (0 != prop);
+       maxLength--;
+       prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
+       ok = (NULL != prop);
 
-    if( ok )
-       strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+       if (ok) {
+               strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+       }
 
-    return( ok );
+       return ok;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
+void
+IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
 {
-  if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
-  
-  super::registerNVRAMController(nvram);
+       if (dtNVRAM) {
+               dtNVRAM->registerNVRAMController(nvram);
+       }
+
+       super::registerNVRAMController(nvram);
 }
 
-int IODTPlatformExpert::haltRestart(unsigned int type)
+int
+IODTPlatformExpert::haltRestart(unsigned int type)
 {
-  if (dtNVRAM) dtNVRAM->sync();
-  
-  return super::haltRestart(type);
+       if (dtNVRAM) {
+               dtNVRAM->sync();
+       }
+
+       return super::haltRestart(type);
 }
 
-IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
-                                      IOByteCount length)
+IOReturn
+IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
+    IOByteCount length)
 {
-  if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->readXPRAM(offset, buffer, length);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
-                                       IOByteCount length)
+IOReturn
+IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
+    IOByteCount length)
 {
-  if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->writeXPRAM(offset, buffer, length);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-IOReturn IODTPlatformExpert::readNVRAMProperty(
+IOReturn
+IODTPlatformExpert::readNVRAMProperty(
        IORegistryEntry * entry,
        const OSSymbol ** name, OSData ** value )
 {
-  if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->readNVRAMProperty(entry, name, value);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-IOReturn IODTPlatformExpert::writeNVRAMProperty(
+IOReturn
+IODTPlatformExpert::writeNVRAMProperty(
        IORegistryEntry * entry,
        const OSSymbol * name, OSData * value )
 {
-  if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->writeNVRAMProperty(entry, name, value);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
+OSDictionary *
+IODTPlatformExpert::getNVRAMPartitions(void)
 {
-  if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
-  else return 0;
+       if (dtNVRAM) {
+               return dtNVRAM->getNVRAMPartitions();
+       } else {
+               return NULL;
+       }
 }
 
-IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
-                                               IOByteCount offset, UInt8 * buffer,
-                                               IOByteCount length)
+IOReturn
+IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
+    IOByteCount offset, UInt8 * buffer,
+    IOByteCount length)
 {
-  if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
-                                                 buffer, length);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->readNVRAMPartition(partitionID, offset,
+                          buffer, length);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
-                                                IOByteCount offset, UInt8 * buffer,
-                                                IOByteCount length)
+IOReturn
+IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
+    IOByteCount offset, UInt8 * buffer,
+    IOByteCount length)
 {
-  if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
-                                                  buffer, length);
-  else return kIOReturnNotReady;
+       if (dtNVRAM) {
+               return dtNVRAM->writeNVRAMPartition(partitionID, offset,
+                          buffer, length);
+       } else {
+               return kIOReturnNotReady;
+       }
 }
 
-IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
+IOByteCount
+IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
 {
-  IOByteCount lengthSaved = 0;
-  
-  if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
-  
-  if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
-  
-  return lengthSaved;
+       IOByteCount lengthSaved = 0;
+
+       if (dtNVRAM) {
+               lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
+       }
+
+       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;
 }
 
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #undef super
@@ -1076,59 +1826,105 @@ IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
 
 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;
+       IORegistryEntry *   dt = NULL;
+       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();
+       // dtTop may be zero on non- device tree systems
+       if (dtTop && (dt = IODeviceTreeAlloc( dtTop ))) {
+               ok = super::init( dt, gIODTPlane );
+       } else {
+               ok = super::init();
+       }
 
-    if( !ok)
-       return( false);
+       if (!ok) {
+               return false;
+       }
 
-    workLoop = IOWorkLoop::workLoop();
-    if (!workLoop)
-        return false;
+       workLoop = IOWorkLoop::workLoop();
+       if (!workLoop) {
+               return false;
+       }
 
-    argsData[ 0 ] = dtTop;
-    argsData[ 1 ] = p2;
-    argsData[ 2 ] = p3;
-    argsData[ 3 ] = p4;
+       return true;
+}
 
-    setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData));
+IOWorkLoop *
+IOPlatformExpertDevice::getWorkLoop() const
+{
+       return workLoop;
+}
 
-    return( true);
+IOReturn
+IOPlatformExpertDevice::setProperties( OSObject * properties )
+{
+       return kIOReturnUnsupported;
 }
 
-IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
+IOReturn
+IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID,
+    UInt32 type, OSDictionary * properties,
+    IOUserClient ** handler )
 {
-    return workLoop;
+       IOReturn            err = kIOReturnSuccess;
+       IOUserClient *      newConnect = NULL;
+       IOUserClient *      theConnect = NULL;
+
+       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;
+       }
+
+       if (newConnect) {
+               if ((false == newConnect->attach(this))
+                   || (false == newConnect->start(this))) {
+                       newConnect->detach( this );
+                       newConnect->release();
+                       err = kIOReturnNotPermitted;
+               } else {
+                       theConnect = newConnect;
+               }
+       }
+
+       *handler = theConnect;
+       return err;
 }
 
-void IOPlatformExpertDevice::free()
+void
+IOPlatformExpertDevice::free()
 {
-    if (workLoop)
-        workLoop->release();
+       if (workLoop) {
+               workLoop->release();
+       }
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -1138,28 +1934,31 @@ void IOPlatformExpertDevice::free()
 
 OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
 
-OSMetaClassDefineReservedUnused(IOPlatformDevice,  0);
-OSMetaClassDefineReservedUnused(IOPlatformDevice,  1);
-OSMetaClassDefineReservedUnused(IOPlatformDevice,  2);
-OSMetaClassDefineReservedUnused(IOPlatformDevice,  3);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-bool IOPlatformDevice::compareName( OSString * name,
-                                       OSString ** matched) const
+bool
+IOPlatformDevice::compareName( OSString * name,
+    OSString ** matched ) const
 {
-    return( ((IOPlatformExpert *)getProvider())->
-               compareNubName( this, name, matched ));
+       return ((IOPlatformExpert *)getProvider())->
+              compareNubName( this, name, matched );
 }
 
-IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
+IOService *
+IOPlatformDevice::matchLocation( IOService * /* client */ )
 {
-    return( this );
+       return this;
 }
 
-IOReturn IOPlatformDevice::getResources( void )
+IOReturn
+IOPlatformDevice::getResources( void )
 {
-    return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
+       return ((IOPlatformExpert *)getProvider())->getNubResources( this );
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -1172,23 +1971,27 @@ IOReturn IOPlatformDevice::getResources( void )
 *********************************************************************/
 
 class IOPanicPlatform : IOPlatformExpert {
-    OSDeclareDefaultStructors(IOPanicPlatform);
+       OSDeclareDefaultStructors(IOPanicPlatform);
 
 public:
-    bool start(IOService * provider);
+       bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
 };
 
 
 OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
 
 
-bool IOPanicPlatform::start(IOService * provider) {
-    const char * platform_name = "(unknown platform name)";
+bool
+IOPanicPlatform::start(IOService * provider)
+{
+       const char * platform_name = "(unknown platform name)";
 
-    if (provider) platform_name = provider->getName();
+       if (provider) {
+               platform_name = provider->getName();
+       }
 
-    panic("Unable to find driver for this platform: \"%s\".\n",
-        platform_name);
+       panic("Unable to find driver for this platform: \"%s\".\n",
+           platform_name);
 
-    return false;
+       return false;
 }