]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPMrootDomain.cpp
xnu-6153.41.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
index 320e8f3f27c928ff441926255e61391afe6b21d9..624d7a812a1934be0739f8b40f7bccc9200c55f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2019 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -31,6 +31,7 @@
 #include <libkern/OSDebug.h>
 #include <IOKit/IOWorkLoop.h>
 #include <IOKit/IOCommandGate.h>
+#include <IOKit/IOTimerEventSource.h>
 #include <IOKit/IOPlatformExpert.h>
 #include <IOKit/IOCPU.h>
 #include <IOKit/IOKitDebug.h>
@@ -47,6 +48,8 @@
 #include "IOPMPowerStateQueue.h"
 #include <IOKit/IOCatalogue.h>
 #include <IOKit/IOReportMacros.h>
+#include <IOKit/IOLib.h>
+#include <IOKit/IOKitKeys.h>
 #include "IOKitKernelInternal.h"
 #if HIBERNATION
 #include <IOKit/IOHibernatePrivate.h>
@@ -89,19 +92,22 @@ __END_DECLS
 #define LOG(x...)    \
     do { kprintf(LOG_PREFIX x); } while (false)
 
-#if DEVELOPMENT
-#define DLOG(x...)  do { \
+#if DEVELOPMENT || DEBUG
+#define DEBUG_LOG(x...) do { \
     if (kIOLogPMRootDomain & gIOKitDebug) \
-       kprintf(LOG_PREFIX x); \
-    else \
-       os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
+    kprintf(LOG_PREFIX x); \
+    os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
 } while (false)
 #else
+#define DEBUG_LOG(x...)
+#endif
+
 #define DLOG(x...)  do { \
     if (kIOLogPMRootDomain & gIOKitDebug) \
        kprintf(LOG_PREFIX x); \
+    else \
+       os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
 } while (false)
-#endif
 
 #define DMSG(x...)  do { \
     if (kIOLogPMRootDomain & gIOKitDebug) { \
@@ -114,7 +120,7 @@ __END_DECLS
 
 #define CHECK_THREAD_CONTEXT
 #ifdef  CHECK_THREAD_CONTEXT
-static IOWorkLoop * gIOPMWorkLoop = 0;
+static IOWorkLoop * gIOPMWorkLoop = NULL;
 #define ASSERT_GATED()                                      \
 do {                                                        \
     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
@@ -192,6 +198,13 @@ static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
 static void notifySystemShutdown( IOService * root, uint32_t messageType );
 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
 static void pmEventTimeStamp(uint64_t *recordTS);
+static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
+static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
+
+static int  IOPMConvertSecondsToCalendar(long secs, IOPMCalendarStruct * dt);
+static long IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
+#define YMDTF       "%04d/%02d/%d %02d:%02d:%02d"
+#define YMDT(cal)   ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
 
 // "IOPMSetSleepSupported"  callPlatformFunction name
 static const OSSymbol *sleepSupportedPEFunction = NULL;
@@ -249,8 +262,8 @@ static const OSSymbol *         gIOPMPSPostDishargeWaitSecondsKey;
 #define kDefaultWranglerIdlePeriod  1000 // in milliseconds
 
 #define kIOSleepWakeFailureString   "SleepWakeFailureString"
-#define kIOOSWatchdogFailureString  "OSWatchdogFailureString"
 #define kIOEFIBootRomFailureKey     "wake-failure"
+#define kIOSleepWakeFailurePanic    "SleepWakeFailurePanic"
 
 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
                           | kIOPMSupportedOnBatt \
@@ -270,20 +283,60 @@ enum {
        OFF_STATE           = 0,
        RESTART_STATE       = 1,
        SLEEP_STATE         = 2,
-       ON_STATE            = 3,
+       AOT_STATE           = 3,
+       ON_STATE            = 4,
        NUM_POWER_STATES
 };
 
+const char *
+getPowerStateString( uint32_t state )
+{
+#define POWER_STATE(x) {(uint32_t) x, #x}
+
+       static const IONamedValue powerStates[] = {
+               POWER_STATE( OFF_STATE ),
+               POWER_STATE( RESTART_STATE ),
+               POWER_STATE( SLEEP_STATE ),
+               POWER_STATE( AOT_STATE ),
+               POWER_STATE( ON_STATE ),
+               { 0, NULL }
+       };
+       return IOFindNameForValue(state, powerStates);
+}
+
 #define ON_POWER        kIOPMPowerOn
 #define RESTART_POWER   kIOPMRestart
 #define SLEEP_POWER     kIOPMAuxPowerOn
 
-static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
-{
-       {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-       {1, kIOPMRestartCapability, kIOPMRestart, RESTART_POWER, 0, 0, 0, 0, 0, 0, 0, 0},
-       {1, kIOPMSleepCapability, kIOPMSleep, SLEEP_POWER, 0, 0, 0, 0, 0, 0, 0, 0},
-       {1, kIOPMPowerOn, kIOPMPowerOn, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0}
+static IOPMPowerState
+    ourPowerStates[NUM_POWER_STATES] =
+{
+       {   .version                = 1,
+           .capabilityFlags        = 0,
+           .outputPowerCharacter   = 0,
+           .inputPowerRequirement  = 0 },
+       {   .version                = 1,
+           .capabilityFlags        = kIOPMRestartCapability,
+           .outputPowerCharacter   = kIOPMRestart,
+           .inputPowerRequirement  = RESTART_POWER },
+       {   .version                = 1,
+           .capabilityFlags        = kIOPMSleepCapability,
+           .outputPowerCharacter   = kIOPMSleep,
+           .inputPowerRequirement  = SLEEP_POWER },
+       {   .version                = 1,
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+           .capabilityFlags        = kIOPMAOTCapability,
+           .outputPowerCharacter   = kIOPMAOTPower,
+           .inputPowerRequirement  = ON_POWER },
+#else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+           .capabilityFlags        = 0,
+           .outputPowerCharacter   = 0,
+           .inputPowerRequirement  = 0xFFFFFFFF },
+#endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+       {   .version                = 1,
+           .capabilityFlags        = kIOPMPowerOn,
+           .outputPowerCharacter   = kIOPMPowerOn,
+           .inputPowerRequirement  = ON_POWER },
 };
 
 #define kIOPMRootDomainWakeTypeSleepService     "SleepService"
@@ -302,6 +355,9 @@ static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
 //
 #define kIOPMSystemCapabilityInterest       "IOPMSystemCapabilityInterest"
 
+// Entitlement required for root domain clients
+#define kRootDomainEntitlementSetProperty   "com.apple.private.iokit.rootdomain-set-property"
+
 #define WAKEEVENT_LOCK()        IOLockLock(wakeEventLock)
 #define WAKEEVENT_UNLOCK()      IOLockUnlock(wakeEventLock)
 
@@ -313,6 +369,26 @@ static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
 
 #define kAggressivesMinValue    1
 
+const char *
+getAggressivenessTypeString( uint32_t type )
+{
+#define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
+
+       static const IONamedValue aggressivenessTypes[] = {
+               AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
+               AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
+               AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
+               AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
+               AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
+               AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
+               AGGRESSIVENESS_TYPE( kPMPowerSource),
+               AGGRESSIVENESS_TYPE( kPMMotionSensor ),
+               AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
+               { 0, NULL }
+       };
+       return IOFindNameForValue(type, aggressivenessTypes);
+}
+
 enum {
        kAggressivesStateBusy           = 0x01,
        kAggressivesStateQuickSpindown  = 0x02
@@ -351,6 +427,33 @@ enum {
        kAggressivesRecordFlagMinValue         = 0x00000002
 };
 
+// System Sleep Preventers
+
+enum {
+       kPMUserDisabledAllSleep = 1,
+       kPMSystemRestartBootingInProgress,
+       kPMConfigPreventSystemSleep,
+       kPMChildPreventSystemSleep,
+       kPMCPUAssertion,
+       kPMPCIUnsupported,
+};
+
+const char *
+getSystemSleepPreventerString( uint32_t preventer )
+{
+#define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
+       static const IONamedValue systemSleepPreventers[] = {
+               SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
+               SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
+               SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
+               SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
+               SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
+               SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
+               { 0, NULL }
+       };
+       return IOFindNameForValue(preventer, systemSleepPreventers);
+}
+
 // gDarkWakeFlags
 enum {
        kDarkWakeFlagHIDTickleEarly      = 0x01,// hid tickle before gfx suppression
@@ -363,7 +466,7 @@ enum {
 };
 
 static IOPMrootDomain * gRootDomain;
-static IONotifier *     gSysPowerDownNotifier = 0;
+static IONotifier *     gSysPowerDownNotifier = NULL;
 static UInt32           gSleepOrShutdownPending = 0;
 static UInt32           gWillShutdown = 0;
 static UInt32           gPagingOff = 0;
@@ -382,22 +485,27 @@ uuid_string_t bootsessionuuid_string;
 
 static uint32_t         gDarkWakeFlags = kDarkWakeFlagHIDTickleNone;
 static uint32_t         gNoIdleFlag = 0;
-static uint32_t         gSwdPanic = 0;
+static uint32_t         gSwdPanic = 1;
 static uint32_t         gSwdSleepTimeout = 0;
 static uint32_t         gSwdWakeTimeout = 0;
 static uint32_t         gSwdSleepWakeTimeout = 0;
 static PMStatsStruct    gPMStats;
+#if DEVELOPMENT || DEBUG
+static uint32_t swd_panic_phase;
+#endif
 
 
 #if HIBERNATION
-static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = 0;
-static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = 0;
+static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = NULL;
+static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
 static void *                           gSleepPolicyTarget;
 #endif
 
 struct timeval gIOLastSleepTime;
 struct timeval gIOLastWakeTime;
 
+struct timeval gIOLastUserSleepTime;
+
 static char gWakeReasonString[128];
 static bool gWakeReasonSysctlRegistered = false;
 static AbsoluteTime gIOLastWakeAbsTime;
@@ -421,9 +529,9 @@ static unsigned int     gPMHaltBusyCount;
 static unsigned int     gPMHaltIdleCount;
 static int              gPMHaltDepth;
 static uint32_t         gPMHaltMessageType;
-static IOLock *         gPMHaltLock  = 0;
-static OSArray *        gPMHaltArray = 0;
-static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
+static IOLock *         gPMHaltLock  = NULL;
+static OSArray *        gPMHaltArray = NULL;
+static const OSSymbol * gPMHaltClientAcknowledgeKey = NULL;
 static bool             gPMQuiesced;
 
 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
@@ -448,7 +556,7 @@ const OSSymbol *gIOPMStatsDriverPSChangeSlow;
  */
 class PMSettingHandle : public OSObject
 {
-       OSDeclareFinalStructors( PMSettingHandle )
+       OSDeclareFinalStructors( PMSettingHandle );
        friend class PMSettingObject;
 
 private:
@@ -462,7 +570,7 @@ private:
  */
 class PMSettingObject : public OSObject
 {
-       OSDeclareFinalStructors( PMSettingObject )
+       OSDeclareFinalStructors( PMSettingObject );
        friend class IOPMrootDomain;
 
 private:
@@ -515,7 +623,7 @@ typedef void (*IOPMTracePointHandler)(
 
 class PMTraceWorker : public OSObject
 {
-       OSDeclareDefaultStructors(PMTraceWorker)
+       OSDeclareDefaultStructors(PMTraceWorker);
 public:
        typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
 
@@ -552,7 +660,7 @@ private:
  */
 class PMAssertionsTracker : public OSObject
 {
-       OSDeclareFinalStructors(PMAssertionsTracker)
+       OSDeclareFinalStructors(PMAssertionsTracker);
 public:
        static PMAssertionsTracker  *pmAssertionsTracker( IOPMrootDomain * );
 
@@ -609,7 +717,7 @@ OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
 
 class PMHaltWorker : public OSObject
 {
-       OSDeclareFinalStructors( PMHaltWorker )
+       OSDeclareFinalStructors( PMHaltWorker );
 
 public:
        IOService *  service;// service being worked on
@@ -632,11 +740,17 @@ OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
 #define super IOService
 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
 
+boolean_t
+IOPMRootDomainGetWillShutdown(void)
+{
+       return gWillShutdown != 0;
+}
+
 static void
 IOPMRootDomainWillShutdown(void)
 {
        if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
-               OSKext::willShutdown();
+               IOService::willShutdown();
                for (int i = 0; i < 100; i++) {
                        if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
                                break;
@@ -771,16 +885,14 @@ IOSystemShutdownNotification(int stage)
 
        startTime = mach_absolute_time();
        IOPMRootDomainWillShutdown();
-       halt_log_enter("IOPMRootDomainWillShutdown", 0, mach_absolute_time() - startTime);
+       halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
 #if HIBERNATION
        startTime = mach_absolute_time();
        IOHibernateSystemPostWake(true);
-       halt_log_enter("IOHibernateSystemPostWake", 0, mach_absolute_time() - startTime);
+       halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
 #endif
        if (OSCompareAndSwap(0, 1, &gPagingOff)) {
-#if !CONFIG_EMBEDDED
                gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
-#endif
        }
 }
 
@@ -862,8 +974,25 @@ IOPMrootDomain::updateConsoleUsers(void)
        IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
        if (tasksSuspended) {
                tasksSuspended = FALSE;
-               tasks_system_suspend(tasksSuspended);
+               updateTasksSuspend();
+       }
+}
+
+void
+IOPMrootDomain::updateTasksSuspend(void)
+{
+       bool newSuspend;
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       newSuspend = (tasksSuspended || _aotTasksSuspended);
+#else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+       newSuspend = tasksSuspended;
+#endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+       if (newSuspend == tasksSuspendState) {
+               return;
        }
+       tasksSuspendState = newSuspend;
+       tasks_system_suspend(newSuspend);
 }
 
 //******************************************************************************
@@ -943,7 +1072,7 @@ sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
 
 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    &gIOLastSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
+    &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
 
 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
@@ -972,7 +1101,7 @@ sysctl_willshutdown
 
 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    0, 0, sysctl_willshutdown, "I", "");
+    NULL, 0, sysctl_willshutdown, "I", "");
 
 extern struct sysctl_oid sysctl__kern_iokittest;
 extern struct sysctl_oid sysctl__debug_iokit;
@@ -1013,11 +1142,11 @@ sysctl_progressmeter
 
 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    0, 0, sysctl_progressmeterenable, "I", "");
+    NULL, 0, sysctl_progressmeterenable, "I", "");
 
 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    0, 0, sysctl_progressmeter, "I", "");
+    NULL, 0, sysctl_progressmeter, "I", "");
 
 #endif /* !CONFIG_EMBEDDED */
 
@@ -1041,7 +1170,7 @@ sysctl_consoleoptions
 
 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
-    0, 0, sysctl_consoleoptions, "I", "");
+    NULL, 0, sysctl_consoleoptions, "I", "");
 
 
 static int
@@ -1101,11 +1230,114 @@ static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTim
 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
+#if DEVELOPMENT || DEBUG
+static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
+#endif
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+//******************************************************************************
+// AOT
+
+static int
+sysctl_aotmetrics SYSCTL_HANDLER_ARGS
+{
+       if (NULL == gRootDomain) {
+               return ENOENT;
+       }
+       if (NULL == gRootDomain->_aotMetrics) {
+               return ENOENT;
+       }
+       return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
+}
+
+static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
+    CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
+    NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
+
+
+static int
+update_aotmode(uint32_t mode)
+{
+       int result;
+
+       if (!gIOPMWorkLoop) {
+               return ENOENT;
+       }
+       result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
+               unsigned int oldCount;
+
+               if (mode && !gRootDomain->_aotMetrics) {
+                       gRootDomain->_aotMetrics = IONewZero(IOPMAOTMetrics, 1);
+                       if (!gRootDomain->_aotMetrics) {
+                               return ENOMEM;
+                       }
+               }
+
+               oldCount = gRootDomain->idleSleepPreventersCount();
+               gRootDomain->_aotMode = mode;
+               gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
+               return 0;
+       });
+       return result;
+}
+
+static int
+sysctl_aotmodebits
+(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
+{
+       int error, changed;
+       uint32_t new_value;
+
+       if (NULL == gRootDomain) {
+               return ENOENT;
+       }
+       error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
+       if (changed && gIOPMWorkLoop) {
+               error = update_aotmode(new_value);
+       }
+
+       return error;
+}
+
+static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
+    NULL, 0, sysctl_aotmodebits, "I", "");
+
+static int
+sysctl_aotmode
+(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
+{
+       int error, changed;
+       uint32_t new_value;
+
+       if (NULL == gRootDomain) {
+               return ENOENT;
+       }
+       error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
+       if (changed && gIOPMWorkLoop) {
+               if (new_value) {
+                       new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
+               }
+               error = update_aotmode(new_value);
+       }
+
+       return error;
+}
+
+static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
+    NULL, 0, sysctl_aotmode, "I", "");
+
+//******************************************************************************
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 
 
 static const OSSymbol * gIOPMSettingAutoWakeCalendarKey;
 static const OSSymbol * gIOPMSettingAutoWakeSecondsKey;
+static const OSSymbol * gIOPMSettingAutoPowerCalendarKey;
+static const OSSymbol * gIOPMSettingAutoPowerSecondsKey;
 static const OSSymbol * gIOPMSettingDebugWakeRelativeKey;
+static const OSSymbol * gIOPMSettingDebugPowerRelativeKey;
 static const OSSymbol * gIOPMSettingMaintenanceWakeCalendarKey;
 static const OSSymbol * gIOPMSettingSleepServiceWakeCalendarKey;
 static const OSSymbol * gIOPMSettingSilentRunningKey;
@@ -1117,7 +1349,8 @@ static const OSSymbol * gIOPMUserIsActiveKey;
 //
 //******************************************************************************
 
-#define kRootDomainSettingsCount        17
+#define kRootDomainSettingsCount           19
+#define kRootDomainNoPublishSettingsCount  3
 
 bool
 IOPMrootDomain::start( IOService * nub )
@@ -1131,7 +1364,10 @@ IOPMrootDomain::start( IOService * nub )
        gRootDomain = this;
        gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
        gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
+       gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
+       gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
        gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
+       gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
        gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
        gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
        gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
@@ -1151,11 +1387,11 @@ IOPMrootDomain::start( IOService * nub )
        {
                OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
                gIOPMSettingAutoWakeSecondsKey,
-               OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey),
+               gIOPMSettingAutoPowerSecondsKey,
                gIOPMSettingAutoWakeCalendarKey,
-               OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey),
+               gIOPMSettingAutoPowerCalendarKey,
                gIOPMSettingDebugWakeRelativeKey,
-               OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey),
+               gIOPMSettingDebugPowerRelativeKey,
                OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
                OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
                OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
@@ -1165,7 +1401,16 @@ IOPMrootDomain::start( IOService * nub )
                OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
                OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
                OSSymbol::withCString(kIOPMStateConsoleShutdown),
-               gIOPMSettingSilentRunningKey
+               OSSymbol::withCString(kIOPMSettingProModeControl),
+               OSSymbol::withCString(kIOPMSettingProModeDefer),
+               gIOPMSettingSilentRunningKey,
+       };
+
+       const OSSymbol  *noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
+       {
+               OSSymbol::withCString(kIOPMSettingProModeControl),
+               OSSymbol::withCString(kIOPMSettingProModeDefer),
+               gIOPMSettingSilentRunningKey,
        };
 
        PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
@@ -1191,6 +1436,14 @@ IOPMrootDomain::start( IOService * nub )
                idleSleepTimerExpired,
                (thread_call_param_t) this);
 
+       powerButtonDown = thread_call_allocate(
+               powerButtonDownCallout,
+               (thread_call_param_t) this);
+
+       powerButtonUp = thread_call_allocate(
+               powerButtonUpCallout,
+               (thread_call_param_t) this);
+
        diskSyncCalloutEntry = thread_call_allocate(
                &disk_sync_callout,
                (thread_call_param_t) this);
@@ -1275,7 +1528,9 @@ IOPMrootDomain::start( IOService * nub )
        // List of PM settings that should not automatically publish itself
        // as a feature when registered by a listener.
        noPublishPMSettings = OSArray::withObjects(
-               (const OSObject **) &gIOPMSettingSilentRunningKey, 1, 0);
+               (const OSObject **)noPublishSettingsArr,
+               kRootDomainNoPublishSettingsCount,
+               0);
 
        fPMSettingsDict = OSDictionary::withCapacity(5);
        preventIdleSleepList = OSSet::withCapacity(8);
@@ -1291,6 +1546,14 @@ IOPMrootDomain::start( IOService * nub )
                &IOPMrootDomain::dispatchPowerEvent));
        gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       _aotMode = 0;
+       _aotTimerES = IOTimerEventSource::timerEventSource(this,
+           OSMemberFunctionCast(IOTimerEventSource::Action,
+           this, &IOPMrootDomain::aotEvaluate));
+       gIOPMWorkLoop->addEventSource(_aotTimerES);
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        // create our power parent
        patriarch = new IORootParent;
        patriarch->init();
@@ -1302,7 +1565,7 @@ IOPMrootDomain::start( IOService * nub )
        changePowerStateToPriv(ON_STATE);
 
        // install power change handler
-       gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
+       gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
 
 #if !NO_KERNEL_HID
        // Register for a notification when IODisplayWrangler is published
@@ -1310,7 +1573,7 @@ IOPMrootDomain::start( IOService * nub )
                _displayWranglerNotifier = addMatchingNotification(
                        gIOPublishNotification, tmpDict,
                        (IOServiceMatchingNotificationHandler) & displayWranglerMatchPublished,
-                       this, 0);
+                       this, NULL);
                tmpDict->release();
        }
 #endif
@@ -1354,6 +1617,8 @@ IOPMrootDomain::start( IOService * nub )
                psIterator->release();
        }
 
+       // read swd_panic boot-arg
+       PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
        sysctl_register_oid(&sysctl__kern_sleeptime);
        sysctl_register_oid(&sysctl__kern_waketime);
        sysctl_register_oid(&sysctl__kern_willshutdown);
@@ -1369,6 +1634,12 @@ IOPMrootDomain::start( IOService * nub )
        sysctl_register_oid(&sysctl__kern_consoleoptions);
        sysctl_register_oid(&sysctl__kern_progressoptions);
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       sysctl_register_oid(&sysctl__kern_aotmode);
+       sysctl_register_oid(&sysctl__kern_aotmodebits);
+       sysctl_register_oid(&sysctl__kern_aotmetrics);
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
 #if HIBERNATION
        IOHibernateSystemInit(this);
 #endif
@@ -1394,7 +1665,46 @@ IOPMrootDomain::setProperties( OSObject * props_obj )
        OSNumber        *n;
        const OSSymbol  *key;
        OSObject        *obj;
-       OSCollectionIterator * iter = 0;
+       OSCollectionIterator * iter = NULL;
+
+       if (!dict) {
+               return kIOReturnBadArgument;
+       }
+
+       bool clientEntitled = false;
+       obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
+       clientEntitled = (obj == kOSBooleanTrue);
+       OSSafeReleaseNULL(obj);
+
+       if (!clientEntitled) {
+               const char * errorSuffix = NULL;
+
+               // IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
+               // That API can set 6 possible keys that are checked below.
+               if ((dict->getCount() == 1) &&
+                   (dict->getObject(gIOPMSettingAutoWakeSecondsKey) ||
+                   dict->getObject(gIOPMSettingAutoPowerSecondsKey) ||
+                   dict->getObject(gIOPMSettingAutoWakeCalendarKey) ||
+                   dict->getObject(gIOPMSettingAutoPowerCalendarKey) ||
+                   dict->getObject(gIOPMSettingDebugWakeRelativeKey) ||
+                   dict->getObject(gIOPMSettingDebugPowerRelativeKey))) {
+                       return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
+                       if (return_value != kIOReturnSuccess) {
+                               errorSuffix = "privileged";
+                       }
+               } else {
+                       return_value = kIOReturnNotPermitted;
+                       errorSuffix = "entitled";
+               }
+
+               if (return_value != kIOReturnSuccess) {
+                       OSString * procName = IOCopyLogNameForPID(proc_selfpid());
+                       DLOG("%s failed, process %s is not %s\n", __func__,
+                           procName ? procName->getCStringNoCopy() : "", errorSuffix);
+                       OSSafeReleaseNULL(procName);
+                       return return_value;
+               }
+       }
 
        const OSSymbol *publish_simulated_battery_string    = OSSymbol::withCString("SoftwareSimulatedBatteries");
        const OSSymbol *boot_complete_string                = OSSymbol::withCString("System Boot Complete");
@@ -1416,11 +1726,6 @@ IOPMrootDomain::setProperties( OSObject * props_obj )
        const OSSymbol *hibernatefreetime_string            = OSSymbol::withCString(kIOHibernateFreeTimeKey);
 #endif
 
-       if (!dict) {
-               return_value = kIOReturnBadArgument;
-               goto exit;
-       }
-
        iter = OSCollectionIterator::withCollection(dict);
        if (!iter) {
                return_value = kIOReturnNoMemory;
@@ -1533,10 +1838,12 @@ IOPMrootDomain::setProperties( OSObject * props_obj )
                                    (data->getLength() == sizeof(IOPMCalendarStruct))) {
                                        const IOPMCalendarStruct * cs =
                                            (const IOPMCalendarStruct *) data->getBytesNoCopy();
-
+                                       IOLog("gIOPMSettingAutoWakeCalendarKey " YMDTF "\n", YMDT(cs));
                                        if (cs->year) {
+                                               _scheduledAlarmUTC = IOPMConvertCalendarToSeconds(cs);
                                                OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
                                        } else {
+                                               _scheduledAlarmUTC = 0;
                                                OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
                                        }
                                        DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
@@ -1631,8 +1938,13 @@ IOPMrootDomain::setAggressiveness(
        AggressivesRequest *    request;
        bool                    found = false;
 
-       DLOG("setAggressiveness(%x) 0x%x = %u\n",
-           (uint32_t) options, (uint32_t) type, (uint32_t) value);
+       if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
+               DLOG("setAggressiveness(%x) %s = %u\n",
+                   (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
+       } else {
+               DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
+                   (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
+       }
 
        request = IONew(AggressivesRequest, 1);
        if (!request) {
@@ -1756,8 +2068,6 @@ IOPMrootDomain::getAggressiveness(
        AGGRESSIVES_UNLOCK();
 
        if (source) {
-               DLOG("getAggressiveness(%d) 0x%x = %u\n",
-                   source, (uint32_t) type, value);
                *outLevel = (unsigned long) value;
                return kIOReturnSuccess;
        } else {
@@ -1783,7 +2093,7 @@ IOPMrootDomain::joinAggressiveness(
                return kIOReturnBadArgument;
        }
 
-       DLOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
+       DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
 
        request = IONew(AggressivesRequest, 1);
        if (!request) {
@@ -1988,14 +2298,14 @@ IOPMrootDomain::synchronizeAggressives(
                if (request->dataType == kAggressivesRequestTypeService) {
                        service = request->data.service;
                } else {
-                       service = 0;
+                       service = NULL;
                }
 
                IODelete(request, AggressivesRequest, 1);
-               request = 0;
+               request = NULL;
 
                if (service) {
-                       if (service->assertPMDriverCall(&callEntry)) {
+                       if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
                                for (i = 0, record = array; i < count; i++, record++) {
                                        value = record->value;
                                        if (record->flags & kAggressivesRecordFlagMinValue) {
@@ -2045,7 +2355,7 @@ IOPMrootDomain::broadcastAggressives(
                                }
 
                                if ((service = OSDynamicCast(IOService, connect->copyChildEntry(gIOPowerPlane)))) {
-                                       if (service->assertPMDriverCall(&callEntry)) {
+                                       if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
                                                for (i = 0, record = array; i < count; i++, record++) {
                                                        if (record->flags & kAggressivesRecordFlagModified) {
                                                                value = record->value;
@@ -2067,6 +2377,31 @@ IOPMrootDomain::broadcastAggressives(
        }
 }
 
+//*****************************************
+// stackshot on power button press
+// ***************************************
+static void
+powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
+{
+       /* Power button pressed during wake
+        * Take a stackshot
+        */
+       DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
+       ((IOPMrootDomain *)us)->takeStackshot(false);
+}
+
+static void
+powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
+{
+       /* Power button released.
+        * Delete any stackshot data
+        */
+       DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
+       ((IOPMrootDomain *)us)->deleteStackshot();
+}
+//*************************************************************************
+//
+
 // MARK: -
 // MARK: System Sleep
 
@@ -2302,7 +2637,6 @@ IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
 //
 // This overrides powerChangeDone in IOService.
 //******************************************************************************
-
 void
 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
 {
@@ -2310,34 +2644,85 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
        uint64_t    timeSinceReset = 0;
 #endif
        uint64_t    now;
+       unsigned long newState;
+       clock_sec_t        secs;
+       clock_usec_t       microsecs;
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       clock_sec_t        adjWakeTime;
+       IOPMCalendarStruct nowCalendar;
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        ASSERT_GATED();
-       DLOG("PowerChangeDone: %u->%u\n",
-           (uint32_t) previousPowerState, (uint32_t) getPowerState());
+       newState = getPowerState();
+       DLOG("PowerChangeDone: %s->%s\n",
+           getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
+
+       if (previousPowerState == newState) {
+               return;
+       }
 
        notifierThread = current_thread();
        switch (getPowerState()) {
        case SLEEP_STATE: {
-               if (previousPowerState != ON_STATE) {
-                       break;
-               }
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
+                       secs = 0;
+                       microsecs = 0;
+                       PEGetUTCTimeOfDay(&secs, &microsecs);
+
+                       adjWakeTime = 0;
+                       if ((kIOPMAOTModeRespectTimers & _aotMode) && (_scheduledAlarmUTC < _aotWakeTimeUTC)) {
+                               IOLog("use _scheduledAlarmUTC\n");
+                               adjWakeTime = _scheduledAlarmUTC;
+                       } else if (_aotExit || (kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) {
+                               IOLog("accelerate _aotWakeTime for exit\n");
+                               adjWakeTime = secs;
+                       } else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
+                               IOLog("accelerate _aotWakeTime for assertion\n");
+                               adjWakeTime = secs;
+                       }
+                       if (adjWakeTime) {
+                               IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
+                       }
 
+                       IOPMConvertSecondsToCalendar(secs, &nowCalendar);
+                       IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
+
+                       IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
+                       assert(kIOReturnSuccess == ret);
+               }
+               if (_aotLastWakeTime) {
+                       _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
+                       if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
+                               strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
+                                   gWakeReasonString,
+                                   sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
+                       }
+               }
+               _aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
                acceptSystemWakeEvents(true);
 
                // re-enable this timer for next sleep
                cancelIdleSleepTimer();
 
-               clock_sec_t     secs;
-               clock_usec_t    microsecs;
                clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
                logtime(secs);
                gIOLastSleepTime.tv_sec  = secs;
                gIOLastSleepTime.tv_usec = microsecs;
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               if (!_aotLastWakeTime) {
+                       gIOLastUserSleepTime = gIOLastSleepTime;
+               }
+#else
+               gIOLastUserSleepTime = gIOLastSleepTime;
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
                gIOLastWakeTime.tv_sec = 0;
                gIOLastWakeTime.tv_usec = 0;
                gIOLastSleepAbsTime = now;
 
                if (wake2DarkwakeDelay && sleepDelaysReport) {
-                       clock_usec_t    microsecs;
                        clock_sec_t     wake2DarkwakeSecs, darkwake2SleepSecs;
                        // Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
 
@@ -2376,6 +2761,8 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
                        clock_usec_t microsecs = 0;
                        uint64_t now_b = mach_absolute_time();
 
+                       secs = 0;
+                       microsecs = 0;
                        PEGetUTCTimeOfDay(&secs, &microsecs);
 
                        uint64_t now_a = mach_absolute_time();
@@ -2401,16 +2788,37 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
                gSleepOrShutdownPending = 0;
 
                // trip the reset of the calendar clock
-               {
-                       clock_sec_t  wakeSecs;
-                       clock_usec_t wakeMicrosecs;
-
-                       clock_wakeup_calendar();
-
-                       clock_get_calendar_microtime(&wakeSecs, &wakeMicrosecs);
-                       gIOLastWakeTime.tv_sec  = wakeSecs;
-                       gIOLastWakeTime.tv_usec = wakeMicrosecs;
+               clock_wakeup_calendar();
+               clock_get_calendar_microtime(&secs, &microsecs);
+               gIOLastWakeTime.tv_sec  = secs;
+               gIOLastWakeTime.tv_usec = microsecs;
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               // aot
+               if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
+                       _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
+                       secs = 0;
+                       microsecs = 0;
+                       PEGetUTCTimeOfDay(&secs, &microsecs);
+                       IOPMConvertSecondsToCalendar(secs, &nowCalendar);
+                       IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
+                       _aotMetrics->sleepCount++;
+                       _aotLastWakeTime = gIOLastWakeAbsTime;
+                       if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
+                               _aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
+                                       = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
+                               _aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
+                                       = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
+                       }
+
+                       if (_aotTestTime) {
+                               if (_aotWakeTimeUTC <= secs) {
+                                       _aotTestTime = _aotTestTime + _aotTestInterval;
+                               }
+                               setWakeTime(_aotTestTime);
+                       }
                }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 
 #if HIBERNATION
                LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
@@ -2434,6 +2842,7 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
                sleepToStandby          = false;
                wranglerTickleLatched   = false;
                userWasActive           = false;
+               isRTCAlarmWake          = false;
                fullWakeReason = kFullWakeReasonNone;
 
                OSString * wakeType = OSDynamicCast(
@@ -2459,9 +2868,11 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
                            !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
                                // Hibernate aborted, or EFI brought up graphics
                                wranglerTickled = true;
-                               DLOG("hibernation aborted %d, options 0x%x\n",
-                                   hibernateAborted,
-                                   hibOptions ? hibOptions->unsigned32BitValue() : 0);
+                               if (hibernateAborted) {
+                                       DLOG("Hibernation aborted\n");
+                               } else {
+                                       DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
+                               }
                        } else
 #endif
                        if (wakeType && (
@@ -2469,6 +2880,9 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
                                    wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
                                // User wake or RTC alarm
                                wranglerTickled = true;
+                               if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
+                                       isRTCAlarmWake = true;
+                               }
                        } else if (wakeType &&
                            wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
                                // SMC standby timer trumps SleepX
@@ -2546,21 +2960,30 @@ IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
 
                thread_call_enter(updateConsoleUsersEntry);
 
-               changePowerStateToPriv(ON_STATE);
-       }   break;
+               changePowerStateToPriv(getRUN_STATE());
+               break;
+       }
 #if !__i386__ && !__x86_64__
-       case ON_STATE: {
-               if (previousPowerState != ON_STATE) {
-                       DLOG("Force re-evaluating aggressiveness\n");
-                       /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
-                       pmPowerStateQueue->submitPowerEvent(
-                               kPowerEventPolicyStimulus,
-                               (void *) kStimulusNoIdleSleepPreventers );
+       case ON_STATE:
+       case AOT_STATE:
+       {
+               DLOG("Force re-evaluating aggressiveness\n");
+               /* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
+               pmPowerStateQueue->submitPowerEvent(
+                       kPowerEventPolicyStimulus,
+                       (void *) kStimulusNoIdleSleepPreventers );
+
+               // After changing to ON_STATE, invalidate any previously queued
+               // request to change to a state less than ON_STATE. This isn't
+               // necessary for AOT_STATE or if the device has only one running
+               // state since the changePowerStateToPriv() issued at the tail
+               // end of SLEEP_STATE case should take care of that.
+               if (getPowerState() == ON_STATE) {
+                       changePowerStateToPriv(ON_STATE);
                }
                break;
        }
-
-#endif
+#endif /* !__i386__ && !__x86_64__ */
        }
        notifierThread = NULL;
 }
@@ -2594,38 +3017,49 @@ IOPMrootDomain::requestPowerDomainState(
 
 bool
 IOPMrootDomain::updatePreventIdleSleepList(
-       IOService * service, bool addNotRemove )
+       IOService * service, bool addNotRemove)
 {
-       unsigned int oldCount, newCount;
+       unsigned int oldCount;
+
+       oldCount = idleSleepPreventersCount();
+       return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
+}
+
+bool
+IOPMrootDomain::updatePreventIdleSleepListInternal(
+       IOService * service, bool addNotRemove, unsigned int oldCount)
+{
+       unsigned int newCount;
 
        ASSERT_GATED();
 
 #if defined(__i386__) || defined(__x86_64__)
        // Disregard disk I/O (besides the display wrangler) as a factor preventing
        // idle sleep, except in the case of legacy disk I/O
-       if ((service != wrangler) && (service != this)) {
+       if (service && (service != wrangler) && (service != this)) {
                return false;
        }
 #endif
 
-       oldCount = preventIdleSleepList->getCount();
-       if (addNotRemove) {
-               preventIdleSleepList->setObject(service);
-               DLOG("prevent idle sleep list: %s+ (%u)\n",
-                   service->getName(), preventIdleSleepList->getCount());
-       } else if (preventIdleSleepList->member(service)) {
-               preventIdleSleepList->removeObject(service);
-               DLOG("prevent idle sleep list: %s- (%u)\n",
-                   service->getName(), preventIdleSleepList->getCount());
+       if (service) {
+               if (addNotRemove) {
+                       preventIdleSleepList->setObject(service);
+                       DLOG("prevent idle sleep list: %s+ (%u)\n",
+                           service->getName(), preventIdleSleepList->getCount());
+               } else if (preventIdleSleepList->member(service)) {
+                       preventIdleSleepList->removeObject(service);
+                       DLOG("prevent idle sleep list: %s- (%u)\n",
+                           service->getName(), preventIdleSleepList->getCount());
+               }
        }
-       newCount = preventIdleSleepList->getCount();
+       newCount = idleSleepPreventersCount();
 
        if ((oldCount == 0) && (newCount != 0)) {
                // Driver added to empty prevent list.
                // Update the driver desire to prevent idle sleep.
                // Driver desire does not prevent demand sleep.
 
-               changePowerStateTo(ON_STATE);
+               changePowerStateTo(getRUN_STATE());
        } else if ((oldCount != 0) && (newCount == 0)) {
                // Last driver removed from prevent list.
                // Drop the driver clamp to allow idle sleep.
@@ -2751,6 +3185,68 @@ IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **syste
        }
 }
 
+void
+IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
+{
+       OSCollectionIterator *iterator = NULL;
+       OSObject    *object = NULL;
+       OSArray     *array = NULL;
+
+       if (!gIOPMWorkLoop->inGate()) {
+               gIOPMWorkLoop->runAction(
+                       OSMemberFunctionCast(IOWorkLoop::Action, this,
+                       &IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
+                       this, (void *)idleSleepList, (void *)systemSleepList);
+               return;
+       }
+
+       if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
+               iterator = OSCollectionIterator::withCollection(preventIdleSleepList);
+               array = OSArray::withCapacity(5);
+
+               while ((object = iterator->getNextObject())) {
+                       IOService *service = OSDynamicCast(IOService, object);
+                       if (object) {
+                               OSDictionary *dict = OSDictionary::withCapacity(2);
+                               if (dict) {
+                                       OSNumber *id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
+                                       dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id);
+                                       dict->setObject(kIOPMDriverAssertionOwnerStringKey, OSSymbol::withCString(service->getName()));
+                                       array->setObject(dict);
+                                       id->release();
+                                       dict->release();
+                               }
+                       }
+               }
+
+               iterator->release();
+               *idleSleepList = array;
+       }
+
+       if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
+               iterator = OSCollectionIterator::withCollection(preventSystemSleepList);
+               array = OSArray::withCapacity(5);
+
+               while ((object = iterator->getNextObject())) {
+                       IOService *service = OSDynamicCast(IOService, object);
+                       if (object) {
+                               OSDictionary *dict = OSDictionary::withCapacity(2);
+                               if (dict) {
+                                       OSNumber *id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
+                                       dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id);
+                                       dict->setObject(kIOPMDriverAssertionOwnerStringKey, OSSymbol::withCString(service->getName()));
+                                       array->setObject(dict);
+                                       id->release();
+                                       dict->release();
+                               }
+                       }
+               }
+
+               iterator->release();
+               *systemSleepList = array;
+       }
+}
+
 //******************************************************************************
 // tellChangeDown
 //
@@ -2760,8 +3256,8 @@ IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **syste
 bool
 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
 {
-       DLOG("tellChangeDown %u->%u\n",
-           (uint32_t) getPowerState(), (uint32_t) stateNum);
+       DLOG("tellChangeDown %s->%s\n",
+           getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
 
        if (SLEEP_STATE == stateNum) {
                // Legacy apps were already told in the full->dark transition
@@ -2804,8 +3300,8 @@ IOPMrootDomain::tellChangeDown( unsigned long stateNum )
 bool
 IOPMrootDomain::askChangeDown( unsigned long stateNum )
 {
-       DLOG("askChangeDown %u->%u\n",
-           (uint32_t) getPowerState(), (uint32_t) stateNum);
+       DLOG("askChangeDown %s->%s\n",
+           getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
 
        // Don't log for dark wake entry
        if (kSystemTransitionSleep == _systemTransitionType) {
@@ -2860,6 +3356,16 @@ IOPMrootDomain::askChangeDownDone(
                        *cancel = true;
                        DLOG("cancel dark->sleep\n");
                }
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
+                       uint64_t now = mach_continuous_time();
+                       if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
+                           && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
+                               *cancel = true;
+                               IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
+                       }
+               }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
        }
 }
 
@@ -2930,8 +3436,8 @@ IOPMrootDomain::systemDidNotSleep( void )
 void
 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
 {
-       DLOG("tellNoChangeDown %u->%u\n",
-           (uint32_t) getPowerState(), (uint32_t) stateNum);
+       DLOG("tellNoChangeDown %s->%s\n",
+           getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
 
        // Sleep canceled, clear the sleep trace point.
        tracePoint(kIOPMTracePointSystemUp);
@@ -2952,8 +3458,8 @@ IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
 void
 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
 {
-       DLOG("tellChangeUp %u->%u\n",
-           (uint32_t) getPowerState(), (uint32_t) stateNum);
+       DLOG("tellChangeUp %s->%s\n",
+           getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
 
        ignoreTellChangeDown = false;
 
@@ -2969,7 +3475,21 @@ IOPMrootDomain::tellChangeUp( unsigned long stateNum )
                        NULL, NULL, NULL);
 
                if (getPowerState() == ON_STATE) {
-                       // this is a quick wake from aborted sleep
+                       // Sleep was cancelled by idle cancel or revert
+                       if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
+                               // rdar://problem/50363791
+                               // If system is in dark wake and sleep is cancelled, do not
+                               // send SystemWillPowerOn/HasPoweredOn messages to kernel
+                               // priority clients. They haven't yet seen a SystemWillSleep
+                               // message before the cancellation. So make sure the kernel
+                               // client bit is cleared in _systemMessageClientMask before
+                               // invoking the tellClients() below. This bit may have been
+                               // set by handleOurPowerChangeStart() anticipating a successful
+                               // sleep and setting the filter mask ahead of time allows the
+                               // SystemWillSleep message to go through.
+                               _systemMessageClientMask &= ~kSystemMessageClientKernel;
+                       }
+
                        systemDidNotSleep();
                        tellClients( kIOMessageSystemWillPowerOn );
                }
@@ -3011,10 +3531,29 @@ IOPMrootDomain::sysPowerDownHandler(
        UInt32 messageType, IOService * service,
        void * messageArgs, vm_size_t argSize )
 {
+       static UInt32 lastSystemMessageType = 0;
        IOReturn    ret = 0;
 
        DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
 
+       // rdar://problem/50363791
+       // Sanity check to make sure the SystemWill/Has message types are
+       // received in the expected order for all kernel priority clients.
+       if (messageType == kIOMessageSystemWillSleep ||
+           messageType == kIOMessageSystemWillPowerOn ||
+           messageType == kIOMessageSystemHasPoweredOn) {
+               switch (messageType) {
+               case kIOMessageSystemWillPowerOn:
+                       assert(lastSystemMessageType == kIOMessageSystemWillSleep);
+                       break;
+               case kIOMessageSystemHasPoweredOn:
+                       assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
+                       break;
+               }
+
+               lastSystemMessageType = messageType;
+       }
+
        if (!gRootDomain) {
                return kIOReturnUnsupported;
        }
@@ -3235,9 +3774,9 @@ IOPMrootDomain::initializeBootSessionUUID(void)
 IOReturn
 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
 {
-       DLOG("changePowerStateTo(%lu)\n", ordinal);
+       DLOG("changePowerStateTo(%u)\n", (uint32_t) ordinal);
 
-       if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE)) {
+       if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
                return kIOReturnUnsupported;
        }
 
@@ -3247,9 +3786,9 @@ IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
 IOReturn
 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
 {
-       DLOG("changePowerStateToPriv(%lu)\n", ordinal);
+       DLOG("changePowerStateToPriv(%u)\n", (uint32_t) ordinal);
 
-       if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE)) {
+       if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
                return kIOReturnUnsupported;
        }
 
@@ -3309,7 +3848,7 @@ IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
                if (!tasksSuspended) {
                        AbsoluteTime deadline;
                        tasksSuspended = TRUE;
-                       tasks_system_suspend(tasksSuspended);
+                       updateTasksSuspend();
 
                        clock_interval_to_deadline(10, kSecondScale, &deadline);
 #if !CONFIG_EMBEDDED
@@ -3317,6 +3856,44 @@ IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
 #endif /* !CONFIG_EMBEDDED */
                }
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               _aotReadyToFullWake = false;
+#if 0
+               if (_aotLingerTime) {
+                       uint64_t deadline;
+                       IOLog("aot linger no return\n");
+                       clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
+                       clock_delay_until(deadline);
+               }
+#endif
+               if (!_aotMode) {
+                       _aotTestTime = 0;
+                       _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
+                       if (_aotMetrics) {
+                               bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
+                       }
+               } else if (!_aotNow && !_debugWakeSeconds) {
+                       _aotNow            = true;
+                       _aotExit           = false;
+                       _aotPendingFlags   = 0;
+                       _aotTasksSuspended = true;
+                       _aotLastWakeTime   = 0;
+                       bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
+                       if (kIOPMAOTModeCycle & _aotMode) {
+                               clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
+                               _aotTestTime = mach_continuous_time() + _aotTestInterval;
+                               setWakeTime(_aotTestTime);
+                       }
+                       uint32_t lingerSecs;
+                       if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
+                               lingerSecs = 0;
+                       }
+                       clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
+                       clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
+                       clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
+               }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
 #if HIBERNATION
                IOHibernateSystemSleep();
                IOHibernateIOKitSleep();
@@ -3362,6 +3939,21 @@ IOPMrootDomain::shouldSleepOnClamshellClosed( void )
        return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled;
 }
 
+bool
+IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
+{
+       // Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
+       // closed && battery
+       if (!clamshellExists) {
+               return false;
+       }
+
+       DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
+           clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled);
+
+       return !acAdaptorConnected && !clamshellSleepDisabled;
+}
+
 void
 IOPMrootDomain::sendClientClamshellNotification( void )
 {
@@ -3544,7 +4136,7 @@ IOPMrootDomain::publishFeature(
                        existing_feature_arr->setObject(new_feature_data);
                        features->setObject(feature, existing_feature_arr);
                        existing_feature_arr->release();
-                       existing_feature_arr = 0;
+                       existing_feature_arr = NULL;
                }
        } else {
                // The easy case: no previously existing features listed. We simply
@@ -3733,8 +4325,8 @@ IOPMrootDomain::setPMSetting(
        const OSSymbol  *type,
        OSObject        *object )
 {
-       PMSettingCallEntry  *entries = 0;
-       OSArray             *chosen  = 0;
+       PMSettingCallEntry  *entries = NULL;
+       OSArray             *chosen  = NULL;
        const OSArray       *array;
        PMSettingObject     *pmso;
        thread_t            thisThread;
@@ -3961,10 +4553,10 @@ IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
                        }
                }
                if (wait) {
-                       assert(0 == pmso->waitThread);
+                       assert(NULL == pmso->waitThread);
                        pmso->waitThread = thisThread;
                        PMSETTING_WAIT(pmso);
-                       pmso->waitThread = 0;
+                       pmso->waitThread = NULL;
                }
        } while (wait);
 
@@ -4113,9 +4705,10 @@ IOPMrootDomain::evaluateSystemSleepPolicy(
        IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
 {
        const IOPMSystemSleepPolicyTable * pt;
-       OSObject *  prop = 0;
+       OSObject *  prop = NULL;
        OSData *    policyData;
        uint64_t    currentFactors = 0;
+       char        currentFactorsBuf[512];
        uint32_t    standbyDelay   = 0;
        uint32_t    powerOffDelay  = 0;
        uint32_t    powerOffTimer  = 0;
@@ -4149,6 +4742,7 @@ IOPMrootDomain::evaluateSystemSleepPolicy(
            sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
            powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
 
+       currentFactorsBuf[0] = 0;
        // pmset level overrides
        if ((*hibMode & kIOHibernateModeOn) == 0) {
                if (!gSleepPolicyHandler) {
@@ -4161,86 +4755,109 @@ IOPMrootDomain::evaluateSystemSleepPolicy(
                // If poweroff is enabled, force poweroff.
                if (standbyEnabled) {
                        currentFactors |= kIOPMSleepFactorStandbyForced;
+                       snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "StandbyForced");
                } else if (powerOffEnabled) {
                        currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
+                       snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "AutoPowerOffForced");
                } else {
                        currentFactors |= kIOPMSleepFactorHibernateForced;
+                       snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "HibernateForced");
                }
        }
 
        // Current factors based on environment and assertions
        if (sleepTimerMaintenance) {
                currentFactors |= kIOPMSleepFactorSleepTimerWake;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "SleepTimerWake");
        }
        if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
                currentFactors |= kIOPMSleepFactorSleepTimerWake;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "SleepTimerWake");
        }
        if (!clamshellClosed) {
                currentFactors |= kIOPMSleepFactorLidOpen;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "LidOpen");
        }
        if (acAdaptorConnected) {
                currentFactors |= kIOPMSleepFactorACPower;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "ACPower");
        }
        if (lowBatteryCondition) {
                currentFactors |= kIOPMSleepFactorBatteryLow;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "BatteryLow");
        }
        if (!standbyDelay || !standbyTimer) {
                currentFactors |= kIOPMSleepFactorStandbyNoDelay;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "StandbyNoDelay");
        }
        if (standbyNixed || !standbyEnabled) {
                currentFactors |= kIOPMSleepFactorStandbyDisabled;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "StandbyDisabled");
        }
        if (resetTimers) {
                currentFactors |= kIOPMSleepFactorLocalUserActivity;
                currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "LocalUserActivity, !SleepTimerWake");
        }
        if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorUSBExternalDevice;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "USBExternalDevice");
        }
        if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "BluetoothHIDDevice");
        }
        if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorExternalMediaMounted;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "ExternalMediaMounted");
        }
        if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorThunderboltDevice;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "ThunderboltDevice");
        }
        if (_scheduledAlarms != 0) {
                currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "RTCAlaramScheduled");
        }
        if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "MagicPacketWakeEnabled");
        }
 #define TCPKEEPALIVE 1
 #if TCPKEEPALIVE
        if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
            kIOPMDriverAssertionLevelOff) {
                currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "NetworkKeepAliveActive");
        }
 #endif
        if (!powerOffEnabled) {
                currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "AutoPowerOffDisabled");
        }
        if (desktopMode) {
                currentFactors |= kIOPMSleepFactorExternalDisplay;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "ExternalDisplay");
        }
        if (userWasActive) {
                currentFactors |= kIOPMSleepFactorLocalUserActivity;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "LocalUserActivity");
        }
        if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
                currentFactors |= kIOPMSleepFactorHibernateFailed;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "HibernateFailed");
        }
        if (thermalWarningState) {
                currentFactors |= kIOPMSleepFactorThermalWarning;
+               snprintf(currentFactorsBuf, sizeof(currentFactorsBuf), "%s, %s", currentFactorsBuf, "ThermalWarning");
        }
 
-       DLOG("sleep factors 0x%llx\n", currentFactors);
+       DLOG("sleep factors 0x%llx %s\n", currentFactors, currentFactorsBuf);
 
        if (gSleepPolicyHandler) {
                uint32_t    savedHibernateMode;
@@ -4524,7 +5141,7 @@ IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
 {
        OSObject *      optionsProp;
        OSDictionary *  optionsDict;
-       OSObject *      obj = 0;
+       OSObject *      obj = NULL;
        OSNumber *      num;
        bool            ok = false;
 
@@ -4677,7 +5294,7 @@ platformHaltRestartApplier( OSObject * object, void * context )
                halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
        }
 
-       ctx->handler = 0;
+       ctx->handler = NULL;
        ctx->Counter++;
 }
 
@@ -4751,7 +5368,13 @@ IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
        }
 
        gHaltRestartCtx.phase = kNotifyHaltRestartAction;
+#if !CONFIG_EMBEDDED
        IOCPURunPlatformHaltRestartActions(pe_type);
+#else
+       if (kPEPagingOff != pe_type) {
+               IOCPURunPlatformHaltRestartActions(pe_type);
+       }
+#endif
 
        // Wait for PM to quiesce
        if ((kPEPagingOff != pe_type) && gPMHaltLock) {
@@ -4876,7 +5499,7 @@ IOPMrootDomain::tagPowerPlaneService(
        }
 
 #if !NO_KERNEL_HID
-       isDisplayWrangler = (0 != service->metaCast("IODisplayWrangler"));
+       isDisplayWrangler = (NULL != service->metaCast("IODisplayWrangler"));
        if (isDisplayWrangler) {
                wrangler = service;
                // found the display wrangler, check for any display assertions already created
@@ -5006,6 +5629,14 @@ IOPMrootDomain::overrideOurPowerChange(
        uint32_t changeFlags = *inOutChangeFlags;
        uint32_t currentPowerState = (uint32_t) getPowerState();
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if ((AOT_STATE == powerState) && (ON_STATE == currentPowerState)) {
+               // Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
+               *inOutChangeFlags |= kIOPMNotDone;
+               return;
+       }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        if (changeFlags & kIOPMParentInitiated) {
                // Root parent is permanently pegged at max power,
                // a parent initiated power change is unexpected.
@@ -5028,11 +5659,11 @@ IOPMrootDomain::overrideOurPowerChange(
                                kIOPMSystemCapabilityAudio);
 
                        // Convert to capability change (ON->ON)
-                       *inOutPowerState = ON_STATE;
+                       *inOutPowerState = getRUN_STATE();
                        *inOutChangeFlags |= kIOPMSynchronize;
 
                        // Revert device desire from SLEEP to ON
-                       changePowerStateToPriv(ON_STATE);
+                       changePowerStateToPriv(getRUN_STATE());
                } else {
                        // System is in dark wake, ok to drop power state.
                        // Broadcast root powering down to entire tree.
@@ -5193,6 +5824,9 @@ IOPMrootDomain::handleOurPowerChangeStart(
                        _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
                }
                if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
+                       // Kernel priority clients are only notified on the initial
+                       // transition to full wake, so don't notify them unless system
+                       // has gained graphics capability since the last system wake.
                        _systemMessageClientMask &= ~kSystemMessageClientKernel;
                }
 #if HIBERNATION
@@ -5214,6 +5848,10 @@ IOPMrootDomain::handleOurPowerChangeStart(
                tracePoint( kIOPMTracePointWakeWillPowerOnClients );
                // Clear stats about sleep
 
+               if (AOT_STATE == powerState) {
+                       _pendingCapability = 0;
+               }
+
                if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
                        willEnterFullWake();
                } else {
@@ -5255,13 +5893,23 @@ IOPMrootDomain::handleOurPowerChangeStart(
                _systemStateGeneration++;
                systemDarkWake = false;
 
-               DLOG("=== START (%u->%u, 0x%x) type %u, gen %u, msg %x, "
+               DLOG("=== START (%s->%s, 0x%x) type %u, gen %u, msg %x, "
                    "dcp %x:%x:%x\n",
-                   currentPowerState, (uint32_t) powerState, *inOutChangeFlags,
+                   getPowerStateString(currentPowerState), getPowerStateString((uint32_t) powerState), *inOutChangeFlags,
                    _systemTransitionType, _systemStateGeneration,
                    _systemMessageClientMask,
                    _desiredCapability, _currentCapability, _pendingCapability);
        }
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if ((AOT_STATE == powerState) && (SLEEP_STATE != currentPowerState)) {
+               panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
+       }
+       if (_aotNow && (ON_STATE == powerState)) {
+               aotShouldExit(false, true);
+               aotExit(false);
+       }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 }
 
 void
@@ -5304,7 +5952,7 @@ IOPMrootDomain::handleOurPowerChangeDone(
                        }
 
                        // Revert device desire to max.
-                       changePowerStateToPriv(ON_STATE);
+                       changePowerStateToPriv(getRUN_STATE());
                } else {
                        // Send message on dark wake to full wake promotion.
                        // tellChangeUp() handles the normal SLEEP->ON case.
@@ -5363,9 +6011,9 @@ IOPMrootDomain::handleOurPowerChangeDone(
                        }
                }
 
-               DLOG("=== FINISH (%u->%u, 0x%x) type %u, gen %u, msg %x, "
+               DLOG("=== FINISH (%s->%s, 0x%x) type %u, gen %u, msg %x, "
                    "dcp %x:%x:%x, dbgtimer %u\n",
-                   currentPowerState, (uint32_t) powerState, changeFlags,
+                   getPowerStateString(currentPowerState), getPowerStateString((uint32_t) powerState), changeFlags,
                    _systemTransitionType, _systemStateGeneration,
                    _systemMessageClientMask,
                    _desiredCapability, _currentCapability, _pendingCapability,
@@ -5432,6 +6080,11 @@ IOPMrootDomain::handleOurPowerChangeDone(
                        DLOG("DisplayOn fullwake request is removed\n");
                        handleDisplayPowerOn();
                }
+
+               if (isRTCAlarmWake) {
+                       pmPowerStateQueue->submitPowerEvent(
+                               kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
+               }
        }
 }
 
@@ -5723,7 +6376,7 @@ IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
 {
        friend class IOPMrootDomain;
-       OSDeclareDefaultStructors(IOPMServiceInterestNotifier)
+       OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
 
 protected:
        uint32_t    ackTimeoutCnt;
@@ -5741,7 +6394,7 @@ IONotifier * IOPMrootDomain::registerInterest(
        IOServiceInterestHandler handler,
        void * target, void * ref )
 {
-       IOPMServiceInterestNotifier *notifier = 0;
+       IOPMServiceInterestNotifier *notifier = NULL;
        bool            isSystemCapabilityClient;
        bool            isKernelCapabilityClient;
        IOReturn        rc = kIOReturnError;;
@@ -5768,7 +6421,7 @@ IONotifier * IOPMrootDomain::registerInterest(
        }
        if (rc != kIOReturnSuccess) {
                notifier->release();
-               notifier = 0;
+               notifier = NULL;
 
                return NULL;
        }
@@ -5835,6 +6488,7 @@ IOPMrootDomain::systemMessageFilter(
        IOPMServiceInterestNotifier *notifier;
 
        notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
+
        do {
                if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
                    (!isCapMsg || !_joinedCapabilityClients ||
@@ -5956,7 +6610,7 @@ IOPMrootDomain::systemMessageFilter(
                        DLOG("destroyed capability client set %p\n",
                            OBFUSCATE(_joinedCapabilityClients));
                        _joinedCapabilityClients->release();
-                       _joinedCapabilityClients = 0;
+                       _joinedCapabilityClients = NULL;
                }
        }
        if (notifier) {
@@ -6090,7 +6744,7 @@ IOPMrootDomain::displayWranglerMatchPublished(
 #if !NO_KERNEL_HID
        // install a handler
        if (!newService->registerInterest( gIOGeneralInterest,
-           &displayWranglerNotification, target, 0)) {
+           &displayWranglerNotification, target, NULL)) {
                return false;
        }
 #endif
@@ -6170,7 +6824,7 @@ void
 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
 {
        pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
-           (void *) 0, options );
+           (void *) NULL, options );
 }
 
 // MARK: -
@@ -6211,18 +6865,18 @@ bool
 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
     uint32_t     sleepReason )
 {
-       int err = 0;
+       uint32_t err = 0;
 
        // Conditions that prevent idle and demand system sleep.
 
        do {
                if (userDisabledAllSleep) {
-                       err = 1; // 1. user-space sleep kill switch
+                       err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
                        break;
                }
 
                if (systemBooting || systemShutdown || gWillShutdown) {
-                       err = 2; // 2. restart or shutdown in progress
+                       err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
                        break;
                }
 
@@ -6235,7 +6889,7 @@ IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
                // dark wake, and must be called from gated context.
 
 #if !CONFIG_SLEEP
-               err = 3;    // 3. config does not support sleep
+               err = kPMConfigPreventSystemSleep;    // 3. config does not support sleep
                break;
 #endif
 
@@ -6248,19 +6902,19 @@ IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
                }
 
                if (preventSystemSleepList->getCount() != 0) {
-                       err = 4; // 4. child prevent system sleep clamp
+                       err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
                        break;
                }
 
                if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
                    kIOPMDriverAssertionLevelOn) {
-                       err = 5; // 5. CPU assertion
+                       err = kPMCPUAssertion; // 5. CPU assertion
                        break;
                }
 
                if (pciCantSleepValid) {
                        if (pciCantSleepFlag) {
-                               err = 6; // 6. PCI card does not support PM (cached)
+                               err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
                        }
                        break;
                } else if (sleepSupportedPEFunction &&
@@ -6282,7 +6936,7 @@ IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
        }while (false);
 
        if (err) {
-               DLOG("System sleep prevented by %d\n", err);
+               DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
                return false;
        }
        return true;
@@ -6321,28 +6975,317 @@ IOPMrootDomain::checkSystemCanSustainFullWake( void )
                // Do not incorporate state that requires graphics to be in max power
                // such as desktopMode or clamshellDisabled.
 
-               if (!acAdaptorConnected) {
-                       DLOG("full wake check: no AC\n");
-                       return false;
-               }
+               if (!acAdaptorConnected) {
+                       DLOG("full wake check: no AC\n");
+                       return false;
+               }
+       }
+#endif
+       return true;
+}
+
+//******************************************************************************
+// mustHibernate
+//******************************************************************************
+
+#if HIBERNATION
+
+bool
+IOPMrootDomain::mustHibernate( void )
+{
+       return lowBatteryCondition || thermalWarningState;
+}
+
+#endif /* HIBERNATION */
+
+//******************************************************************************
+// AOT
+//******************************************************************************
+
+// Tables for accumulated days in year by month, latter used for leap years
+
+static const int daysbymonth[] =
+{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+static const int lydaysbymonth[] =
+{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
+
+static int __unused
+IOPMConvertSecondsToCalendar(long secs, IOPMCalendarStruct * dt)
+{
+       const int *             dbm = daysbymonth;
+       long                    n, x, y, z;
+
+       if (secs < 0) {
+               return 0;
+       }
+
+       // Calculate seconds, minutes and hours
+
+       n = secs % (24 * 3600);
+       dt->second = n % 60;
+       n /= 60;
+       dt->minute = n % 60;
+       dt->hour = n / 60;
+
+       // Calculate day of week
+
+       n = secs / (24 * 3600);
+//     dt->dayWeek = (n + 4) % 7;
+
+       // Calculate year
+       // Rebase from days since Unix epoch (1/1/1970) store in 'n',
+       // to days since 1/1/1968 to start on 4 year cycle, beginning
+       // on a leap year.
+
+       n += (366 + 365);
+
+       // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
+       // Valid before 2100, since 2100 is not a leap year.
+
+       x = n / 1461;       // number of 4 year cycles
+       y = n % 1461;       // days into current 4 year cycle
+       z = 1968 + (4 * x);
+
+       // Add in years in the current 4 year cycle
+
+       if (y >= 366) {
+               y -= 366;   // days after the leap year
+               n = y % 365; // days into the current year
+               z += (1 + y / 365); // years after the past 4-yr cycle
+       } else {
+               n = y;
+               dbm = lydaysbymonth;
+       }
+       if (z > 2099) {
+               return 0;
+       }
+
+       dt->year = z;
+
+       // Adjust remaining days value to start at 1
+
+       n += 1;
+
+       // Calculate month
+
+       for (x = 1; n > dbm[x]; x++) {
+               continue;
+       }
+       dt->month = x;
+
+       // Calculate day of month
+
+       dt->day = n - dbm[x - 1];
+
+       return 1;
+}
+
+static long
+IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
+{
+       const int *             dbm = daysbymonth;
+       long                    y, secs, days;
+
+       if (dt->year < 1970) {
+               return 0;
+       }
+
+       // Seconds elapsed in the current day
+
+       secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
+
+       // Number of days from 1/1/70 to beginning of current year
+       // Account for extra day every 4 years starting at 1973
+
+       y = dt->year - 1970;
+       days = (y * 365) + ((y + 1) / 4);
+
+       // Change table if current year is a leap year
+
+       if ((dt->year % 4) == 0) {
+               dbm = lydaysbymonth;
+       }
+
+       // Add in days elapsed in the current year
+
+       days += (dt->day - 1) + dbm[dt->month - 1];
+
+       // Add accumulated days to accumulated seconds
+
+       secs += 24 * 3600 * days;
+
+       return secs;
+}
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+
+unsigned long
+IOPMrootDomain::getRUN_STATE(void)
+{
+       return _aotNow ? AOT_STATE : ON_STATE;
+}
+
+bool
+IOPMrootDomain::isAOTMode()
+{
+       return _aotNow;
+}
+
+IOReturn
+IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
+{
+       clock_sec_t     nowsecs, wakesecs;
+       clock_usec_t    nowmicrosecs, wakemicrosecs;
+       uint64_t        nowAbs, wakeAbs;
+
+       clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
+       wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
+       if (wakeAbs < nowAbs) {
+               printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
+               wakeAbs = nowAbs;
+       }
+       wakeAbs -= nowAbs;
+       absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
+
+       wakesecs += nowsecs;
+       wakemicrosecs += nowmicrosecs;
+       if (wakemicrosecs >= USEC_PER_SEC) {
+               wakesecs++;
+               wakemicrosecs -= USEC_PER_SEC;
+       }
+       if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
+               wakesecs++;
+       }
+
+       IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
+
+       if (_aotWakeTimeContinuous != wakeContinuousTime) {
+               _aotWakeTimeContinuous = wakeContinuousTime;
+               IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
+       }
+       _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
+       _aotWakeTimeUTC               = wakesecs;
+
+       return kIOReturnSuccess;
+}
+
+// assumes WAKEEVENT_LOCK
+bool
+IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
+{
+       bool exitNow;
+       const char * reason = "";
+
+       if (software) {
+               _aotExit = true;
+               _aotMetrics->softwareRequestCount++;
+               reason = "software request";
+       } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
+               _aotExit = true;
+               reason = gWakeReasonString;
+       } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
+               _aotExit = true;
+               _aotMetrics->noTimeSetCount++;
+               reason = "flipbook expired";
+       } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _scheduledAlarmUTC) {
+               clock_sec_t     sec;
+               clock_usec_t    usec;
+               clock_get_calendar_microtime(&sec, &usec);
+               if (_scheduledAlarmUTC <= sec) {
+                       _aotExit = true;
+                       _aotMetrics->rtcAlarmsCount++;
+                       reason = "user alarm";
+               }
+       }
+       exitNow = (_aotNow && _aotExit);
+       if (exitNow) {
+               _aotNow = false;
+               IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
+                   reason,
+                   _aotMetrics->sleepCount,
+                   _aotMetrics->possibleCount,
+                   _aotMetrics->confirmedPossibleCount,
+                   _aotMetrics->rejectedPossibleCount,
+                   _aotMetrics->expiredPossibleCount,
+                   _aotMetrics->noTimeSetCount,
+                   _aotMetrics->rtcAlarmsCount);
+       }
+       return exitNow;
+}
+
+void
+IOPMrootDomain::aotExit(bool cps)
+{
+       _aotTasksSuspended  = false;
+       _aotReadyToFullWake = false;
+       if (_aotTimerScheduled) {
+               _aotTimerES->cancelTimeout();
+               _aotTimerScheduled = false;
+       }
+       updateTasksSuspend();
+
+       _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
+       _aotLastWakeTime = 0;
+       if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
+               strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
+                   gWakeReasonString,
+                   sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
+       }
+
+       _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
+
+       _systemMessageClientMask = kSystemMessageClientLegacyApp;
+       tellClients(kIOMessageSystemWillPowerOn);
+
+       if (cps) {
+               changePowerStateToPriv(getRUN_STATE());
+       }
+}
+
+void
+IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
+{
+       bool exitNow;
+
+       IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
+
+       WAKEEVENT_LOCK();
+       exitNow = aotShouldExit(false, false);
+       if (timer != NULL) {
+               _aotTimerScheduled = false;
        }
+       WAKEEVENT_UNLOCK();
+       if (exitNow) {
+               aotExit(true);
+       } else {
+#if 0
+               if (_aotLingerTime) {
+                       uint64_t deadline;
+                       IOLog("aot linger before sleep\n");
+                       clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
+                       clock_delay_until(deadline);
+               }
 #endif
-       return true;
+               privateSleepSystem(kIOPMSleepReasonSoftware);
+       }
 }
 
-//******************************************************************************
-// mustHibernate
-//******************************************************************************
+#else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 
-#if HIBERNATION
+unsigned long
+IOPMrootDomain::getRUN_STATE(void)
+{
+       return ON_STATE;
+}
 
-bool
-IOPMrootDomain::mustHibernate( void )
+IOReturn
+IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
 {
-       return lowBatteryCondition || thermalWarningState;
+       return kIOReturnUnsupported;
 }
 
-#endif /* HIBERNATION */
+#endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 
 //******************************************************************************
 // adjustPowerState
@@ -6357,13 +7300,45 @@ IOPMrootDomain::mustHibernate( void )
 void
 IOPMrootDomain::adjustPowerState( bool sleepASAP )
 {
-       DLOG("adjustPowerState ps %u, asap %d, idleSleepEnabled %d\n",
-           (uint32_t) getPowerState(), sleepASAP, idleSleepEnabled);
+       DEBUG_LOG("adjustPowerState ps %s, asap %d, idleSleepEnabled %d\n",
+           getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
 
        ASSERT_GATED();
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if (_aotNow) {
+               bool exitNow;
+
+               if (AOT_STATE != getPowerState()) {
+                       return;
+               }
+               WAKEEVENT_LOCK();
+               exitNow = aotShouldExit(true, false);
+               if (!exitNow
+                   && !_aotTimerScheduled
+                   && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
+                       _aotTimerScheduled = true;
+                       if (_aotLingerTime) {
+                               _aotTimerES->setTimeout(_aotLingerTime);
+                       } else {
+                               _aotTimerES->setTimeout(800, kMillisecondScale);
+                       }
+               }
+               WAKEEVENT_UNLOCK();
+               if (exitNow) {
+                       aotExit(true);
+               } else {
+                       _aotReadyToFullWake = true;
+                       if (!_aotTimerScheduled) {
+                               privateSleepSystem(kIOPMSleepReasonSoftware);
+                       }
+               }
+               return;
+       }
+#endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
-               changePowerStateToPriv(ON_STATE);
+               changePowerStateToPriv(getRUN_STATE());
        } else if (sleepASAP) {
                changePowerStateToPriv(SLEEP_STATE);
        }
@@ -6493,7 +7468,7 @@ IOPMrootDomain::dispatchPowerEvent(
                DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
                if (systemCapabilityNotifier) {
                        systemCapabilityNotifier->release();
-                       systemCapabilityNotifier = 0;
+                       systemCapabilityNotifier = NULL;
                }
                if (arg0) {
                        systemCapabilityNotifier = (IONotifier *) arg0;
@@ -6692,8 +7667,24 @@ exit:
 IOReturn
 IOPMrootDomain::receivePowerNotification( UInt32 msg )
 {
-       pmPowerStateQueue->submitPowerEvent(
-               kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
+       if (msg & kIOPMPowerButton) {
+               uint32_t currentPhase = pmTracer->getTracePhase();
+               if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
+                       DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
+                       swd_flags |= SWD_PWR_BTN_STACKSHOT;
+                       thread_call_enter(powerButtonDown);
+               } else {
+                       DEBUG_LOG("power button pressed when system is up\n");
+               }
+       } else if (msg & kIOPMPowerButtonUp) {
+               if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
+                       swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
+                       thread_call_enter(powerButtonUp);
+               }
+       } else {
+               pmPowerStateQueue->submitPowerEvent(
+                       kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
+       }
        return kIOReturnSuccess;
 }
 
@@ -6701,6 +7692,7 @@ void
 IOPMrootDomain::handlePowerNotification( UInt32 msg )
 {
        bool        eval_clamshell = false;
+       bool        eval_clamshell_alarm = false;
 
        ASSERT_GATED();
 
@@ -6708,7 +7700,16 @@ IOPMrootDomain::handlePowerNotification( UInt32 msg )
         * Local (IOPMrootDomain only) eval clamshell command
         */
        if (msg & kLocalEvalClamshellCommand) {
-               eval_clamshell = true;
+               if (isRTCAlarmWake) {
+                       eval_clamshell_alarm = true;
+
+                       // reset isRTCAlarmWake. This evaluation should happen only once
+                       // on RTC/Alarm wake. Any clamshell events after wake should follow
+                       // the regular evaluation
+                       isRTCAlarmWake = false;
+               } else {
+                       eval_clamshell = true;
+               }
        }
 
        /*
@@ -6883,7 +7884,11 @@ IOPMrootDomain::handlePowerNotification( UInt32 msg )
        /*
         * Evaluate clamshell and SLEEP if appropiate
         */
-       if (eval_clamshell && clamshellClosed) {
+       if (eval_clamshell_alarm && clamshellClosed) {
+               if (shouldSleepOnRTCAlarmWake()) {
+                       privateSleepSystem(kIOPMSleepReasonClamshell);
+               }
+       } else if (eval_clamshell && clamshellClosed) {
                if (shouldSleepOnClamshellClosed()) {
                        privateSleepSystem(kIOPMSleepReasonClamshell);
                } else {
@@ -6891,22 +7896,16 @@ IOPMrootDomain::handlePowerNotification( UInt32 msg )
                }
        }
 
-       /*
-        * Power Button
-        */
-       if (msg & kIOPMPowerButton) {
-               DLOG("Powerbutton press\n");
-               if (!wranglerAsleep) {
-                       OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
-                       // Check that power button sleep is enabled
-                       if (pbs) {
-                               if (kOSBooleanTrue != getProperty(pbs)) {
-                                       privateSleepSystem(kIOPMSleepReasonPowerButton);
-                               }
-                       }
-               } else {
-                       reportUserInput();
-               }
+       if (msg & kIOPMProModeEngaged) {
+               int newState = 1;
+               DLOG("ProModeEngaged\n");
+               messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier, &newState, sizeof(newState));
+       }
+
+       if (msg & kIOPMProModeDisengaged) {
+               int newState = 0;
+               DLOG("ProModeDisengaged\n");
+               messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier, &newState, sizeof(newState));
        }
 }
 
@@ -6966,7 +7965,7 @@ IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
                        if (kFullWakeReasonDisplayOn == fullWakeReason) {
                                fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
                                DLOG("User activity while in notification wake\n");
-                               changePowerStateWithOverrideTo( ON_STATE, 0);
+                               changePowerStateWithOverrideTo( getRUN_STATE(), 0);
                        }
 
                        kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
@@ -7166,7 +8165,7 @@ IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
                                // Release power clamp, and wait for children idle.
                                adjustPowerState(true);
                        } else {
-                               changePowerStateToPriv(ON_STATE);
+                               changePowerStateToPriv(getRUN_STATE());
                        }
                }
        }
@@ -7210,7 +8209,7 @@ IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
        if (flags.bit.idleSleepEnabled) {
                DLOG("idle sleep timer enabled\n");
                if (!wrangler) {
-                       changePowerStateToPriv(ON_STATE);
+                       changePowerStateToPriv(getRUN_STATE());
                        startIdleSleepTimer( idleSeconds );
                } else {
                        // Start idle timer if prefs now allow system sleep
@@ -7233,9 +8232,9 @@ IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
        if (flags.bit.adjustPowerState) {
                bool sleepASAP = false;
 
-               if (!systemBooting && (preventIdleSleepList->getCount() == 0)) {
+               if (!systemBooting && (0 == idleSleepPreventersCount())) {
                        if (!wrangler) {
-                               changePowerStateToPriv(ON_STATE);
+                               changePowerStateToPriv(getRUN_STATE());
                                if (idleSleepEnabled) {
                                        // stay awake for at least idleSeconds
                                        startIdleSleepTimer(idleSeconds);
@@ -7249,6 +8248,28 @@ IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
        }
 }
 
+//******************************************************************************
+
+unsigned int
+IOPMrootDomain::idleSleepPreventersCount()
+{
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if (_aotMode) {
+               unsigned int count __block;
+               count = 0;
+               preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
+               {
+                       count += (NULL == obj->metaCast("AppleARMBacklight"));
+                       return false;
+               });
+               return count;
+       }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
+       return preventIdleSleepList->getCount();
+}
+
+
 //******************************************************************************
 // requestFullWake
 //
@@ -7259,7 +8280,7 @@ void
 IOPMrootDomain::requestFullWake( FullWakeReason reason )
 {
        uint32_t        options = 0;
-       IOService *     pciRoot = 0;
+       IOService *     pciRoot = NULL;
        bool            promotion = false;
 
        // System must be in dark wake and a valid reason for entering full wake
@@ -7393,6 +8414,13 @@ IOPMrootDomain::fullWakeDelayedWork( void )
 // evaluateAssertions
 //
 //******************************************************************************
+
+// Bitmask of all kernel assertions that prevent system idle sleep.
+// kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
+#define NO_IDLE_SLEEP_ASSERTIONS_MASK \
+       (kIOPMDriverAssertionReservedBit7 | \
+        kIOPMDriverAssertionPreventSystemIdleSleepBit)
+
 void
 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
 {
@@ -7410,7 +8438,14 @@ IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDr
        }
 
        if (changedBits & kIOPMDriverAssertionCPUBit) {
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               if (_aotNow) {
+                       IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
+               }
+               evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
+#else
                evaluatePolicy(kStimulusDarkWakeEvaluate);
+#endif
                if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
                        AbsoluteTime    now;
                        clock_usec_t    microsecs;
@@ -7424,13 +8459,18 @@ IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDr
                }
        }
 
-       if (changedBits & kIOPMDriverAssertionReservedBit7) {
-               bool value = (newAssertions & kIOPMDriverAssertionReservedBit7) ? true : false;
-               if (value) {
-                       DLOG("Driver assertion ReservedBit7 raised. Legacy IO preventing sleep\n");
-                       updatePreventIdleSleepList(this, true);
+       if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
+               if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
+                       if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
+                               DLOG("PreventIdleSleep driver assertion raised\n");
+                               bool ok = updatePreventIdleSleepList(this, true);
+                               if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
+                                       // Cancel idle sleep if there is one in progress
+                                       cancelIdlePowerDown(this);
+                               }
+                       }
                } else {
-                       DLOG("Driver assertion ReservedBit7 dropped\n");
+                       DLOG("PreventIdleSleep driver assertion dropped\n");
                        updatePreventIdleSleepList(this, false);
                }
        }
@@ -7513,7 +8553,7 @@ IOPMrootDomain::pmStatsRecordApplicationResponse(
        OSNumber        *msgNum                 = NULL;
        const OSSymbol  *appname;
        const OSSymbol  *sleep = NULL, *wake = NULL;
-       IOPMServiceInterestNotifier *notify = 0;
+       IOPMServiceInterestNotifier *notify = NULL;
 
        if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
                if (response->isEqualTo(gIOPMStatsResponseTimedOut)) {
@@ -8032,6 +9072,14 @@ PMTraceWorker::RTC_TRACE(void)
                tracePointHandler( tracePointTarget, traceData32, wordA );
                _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
        }
+#if DEVELOPMENT || DEBUG
+       if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
+               DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
+               IOLock *l = IOLockAlloc();
+               IOLockLock(l);
+               IOLockLock(l);
+       }
+#endif
 }
 
 int
@@ -8229,7 +9277,7 @@ PMHaltWorker::worker( void )
        if (me) {
                me->release();
        }
-       return 0;
+       return NULL;
 }
 
 void
@@ -8238,7 +9286,7 @@ PMHaltWorker::free( void )
        DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
        if (lock) {
                IOLockFree(lock);
-               lock = 0;
+               lock = NULL;
        }
        return OSObject::free();
 }
@@ -8291,7 +9339,7 @@ PMHaltWorker::work( PMHaltWorker * me )
        bool            timeout;
 
        while (true) {
-               service = 0;
+               service = NULL;
                timeout = false;
 
                // Claim an unit of work from the shared pool
@@ -8325,7 +9373,7 @@ PMHaltWorker::work( PMHaltWorker * me )
                        while (service->getProperty(gPMHaltClientAcknowledgeKey)) {
                                IOLockSleep(me->lock, me, THREAD_UNINT);
                        }
-                       me->service = 0;
+                       me->service = NULL;
                        timeout = me->timeout;
                        IOLockUnlock(me->lock);
                }
@@ -8754,7 +9802,7 @@ IOPMrootDomain::copyProperty( const char * aKey) const
        }
 
        if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
-               OSArray * array = 0;
+               OSArray * array = NULL;
                WAKEEVENT_LOCK();
                if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
                        OSCollection *collection = _systemWakeEventsArray->copyCollection();
@@ -8767,7 +9815,7 @@ IOPMrootDomain::copyProperty( const char * aKey) const
        }
 
        if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
-               OSArray * array = 0;
+               OSArray * array = NULL;
                IOLockLock(pmStatsLock);
                if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
                        OSCollection *collection = pmStatsAppResponses->copyCollection();
@@ -8792,6 +9840,17 @@ IOPMrootDomain::copyProperty( const char * aKey) const
                return systemSleepList;
        }
 
+       if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
+               OSArray *idleSleepList = NULL;
+               gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
+               return idleSleepList;
+       }
+
+       if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
+               OSArray *systemSleepList = NULL;
+               gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
+               return systemSleepList;
+       }
        return NULL;
 }
 
@@ -8819,12 +9878,18 @@ IOPMrootDomain::acceptSystemWakeEvents( bool accept )
 
        WAKEEVENT_LOCK();
        if (accept) {
-               gWakeReasonString[0] = '\0';
                if (!_systemWakeEventsArray) {
                        _systemWakeEventsArray = OSArray::withCapacity(4);
                }
-               if ((_acceptSystemWakeEvents = (_systemWakeEventsArray != 0))) {
-                       _systemWakeEventsArray->flushCollection();
+               _acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+               if (!(kIOPMWakeEventAOTExitFlags & _aotPendingFlags))
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+               {
+                       gWakeReasonString[0] = '\0';
+                       if (_systemWakeEventsArray) {
+                               _systemWakeEventsArray->flushCollection();
+                       }
                }
        } else {
                _acceptSystemWakeEvents = false;
@@ -8835,7 +9900,7 @@ IOPMrootDomain::acceptSystemWakeEvents( bool accept )
 
                if ((panic_allowed == -1) &&
                    (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
-                       panic_allowed = 1;
+                       panic_allowed = 0;
                }
 
                if (panic_allowed) {
@@ -8873,14 +9938,15 @@ IOPMrootDomain::claimSystemWakeEvent(
        const char *    reason,
        OSObject *      details )
 {
-       const OSSymbol *    deviceName   = 0;
-       OSNumber *          deviceRegId  = 0;
-       OSNumber *          claimTime    = 0;
-       OSData *            flagsData    = 0;
-       OSString *          reasonString = 0;
-       OSDictionary *      d = 0;
+       const OSSymbol *    deviceName   = NULL;
+       OSNumber *          deviceRegId  = NULL;
+       OSNumber *          claimTime    = NULL;
+       OSData *            flagsData    = NULL;
+       OSString *          reasonString = NULL;
+       OSDictionary *      d = NULL;
        uint64_t            timestamp;
        bool                ok = false;
+       bool                addWakeReason;
 
        pmEventTimeStamp(&timestamp);
 
@@ -8888,6 +9954,32 @@ IOPMrootDomain::claimSystemWakeEvent(
                return;
        }
 
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       IOOptionBits        aotFlags = 0;
+       bool                needAOTEvaluate = FALSE;
+
+       if (kIOPMAOTModeAddEventFlags & _aotMode) {
+               if (!strcmp("hold", reason)
+                   || !strcmp("help", reason)
+                   || !strcmp("menu", reason)
+                   || !strcmp("stockholm", reason)
+                   || !strcmp("ringer", reason)
+                   || !strcmp("ringerab", reason)
+                   || !strcmp("smc0", reason)
+                   || !strcmp("AOP.RTPWakeupAP", reason)
+                   || !strcmp("BT.OutboxNotEmpty", reason)
+                   || !strcmp("WL.OutboxNotEmpty", reason)) {
+                       flags |= kIOPMWakeEventAOTExit;
+               }
+       }
+
+#if DEVELOPMENT || DEBUG
+       if (_aotLingerTime && !strcmp("rtc", reason)) {
+               flags |= kIOPMWakeEventAOTPossibleExit;
+       }
+#endif /* DEVELOPMENT || DEBUG */
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        deviceName   = device->copyName(gIOServicePlane);
        deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
        claimTime    = OSNumber::withNumber(timestamp, 64);
@@ -8908,6 +10000,34 @@ IOPMrootDomain::claimSystemWakeEvent(
        }
 
        WAKEEVENT_LOCK();
+       addWakeReason = _acceptSystemWakeEvents;
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if (_aotMode) {
+               IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
+       }
+       aotFlags        = (kIOPMWakeEventAOTFlags & flags);
+       aotFlags        = (aotFlags & ~_aotPendingFlags);
+       needAOTEvaluate = false;
+       if (_aotNow && aotFlags) {
+               if (kIOPMWakeEventAOTPossibleExit & flags) {
+                       _aotMetrics->possibleCount++;
+               }
+               if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
+                       _aotMetrics->confirmedPossibleCount++;
+               }
+               if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
+                       _aotMetrics->rejectedPossibleCount++;
+               }
+               if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
+                       _aotMetrics->expiredPossibleCount++;
+               }
+
+               _aotPendingFlags |= aotFlags;
+               addWakeReason     = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
+               needAOTEvaluate   = _aotReadyToFullWake;
+       }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
+
        if (!gWakeReasonSysctlRegistered) {
                // Lazy registration until the platform driver stops registering
                // the same name.
@@ -8916,14 +10036,20 @@ IOPMrootDomain::claimSystemWakeEvent(
                sysctl_register_oid(&sysctl__kern_wakereason);
 #endif
        }
-       if (_acceptSystemWakeEvents) {
+       if (addWakeReason) {
                ok = _systemWakeEventsArray->setObject(d);
                if (gWakeReasonString[0] != '\0') {
                        strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
                }
                strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
        }
+
        WAKEEVENT_UNLOCK();
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+       if (needAOTEvaluate) {
+               aotEvaluate(NULL);
+       }
+#endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
 
 done:
        if (deviceName) {
@@ -8959,7 +10085,7 @@ PMSettingHandle::free( void )
        if (pmso) {
                pmso->clientHandleFreed();
                pmso->release();
-               pmso = 0;
+               pmso = NULL;
        }
 
        OSObject::free();
@@ -8985,8 +10111,8 @@ PMSettingObject *PMSettingObject::pmSettingObject(
        OSObject                            * *handle_obj)
 {
        uint32_t                            settingCount = 0;
-       PMSettingObject                     *pmso = 0;
-       PMSettingHandle                     *pmsh = 0;
+       PMSettingObject                     *pmso = NULL;
+       PMSettingHandle                     *pmsh = NULL;
 
        if (!parent_arg || !handler_arg || !settings || !handle_obj) {
                return NULL;
@@ -9253,7 +10379,7 @@ PMAssertionsTracker::createAssertion(
        track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
        track.level = level;
        track.assertionBits = which;
-       track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs):0;
+       track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs):NULL;
        track.ownerService = serviceID;
        track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
        track.modifiedTime = 0;
@@ -9313,7 +10439,7 @@ PMAssertionsTracker::releaseAssertion(
        IOPMDriverAssertionID _id)
 {
        if (owner && owner->pmPowerStateQueue) {
-               owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, 0, _id);
+               owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
        }
        return kIOReturnSuccess;
 }
@@ -9385,7 +10511,7 @@ PMAssertionsTracker::setUserAssertionLevels(
                                this,
                                &PMAssertionsTracker::handleSetUserAssertionLevels),
                        this,
-                       (void *) &new_user_levels, 0, 0, 0);
+                       (void *) &new_user_levels, NULL, NULL, NULL);
        }
 
        return kIOReturnSuccess;
@@ -9645,7 +10771,7 @@ IOPMrootDomain::getWatchdogTimeout()
 IOReturn
 IOPMrootDomain::restartWithStackshot()
 {
-       takeStackshot(true, true, false);
+       takeStackshot(true);
 
        return kIOReturnSuccess;
 }
@@ -9653,7 +10779,7 @@ IOPMrootDomain::restartWithStackshot()
 void
 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
 {
-       takeStackshot(wdogTrigger, false, false);
+       takeStackshot(wdogTrigger);
 }
 
 void
@@ -9810,39 +10936,72 @@ IOPMrootDomain::saveFailureData2File()
        char  failureStr[512];
        errno_t error;
        char *outbuf;
-       bool oswatchdog = false;
+       OSNumber *statusCode;
+       uint64_t pmStatusCode = 0;
+       uint32_t phaseData = 0;
+       uint32_t phaseDetail = 0;
+       bool efiFailure = false;
+
+       statusCode = OSDynamicCast(OSNumber, getProperty(kIOPMSleepWakeFailureCodeKey));
+       if (statusCode) {
+               pmStatusCode = statusCode->unsigned64BitValue();
+               phaseData = pmStatusCode & 0xFFFFFFFF;
+               phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
+               if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
+                       LOG("Sleep Wake failure in EFI\n");
+                       efiFailure = true;
+                       failureStr[0] = 0;
+                       snprintf(failureStr, sizeof(failureStr), "Sleep Wake failure in EFI\n\nFailure code:: 0x%08x 0x%08x\n\nPlease IGNORE the below stackshot\n", phaseDetail, phaseData);
+                       len = strlen(failureStr);
+               }
+       }
+
+       if (!efiFailure) {
+               if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
+                       swd_flags |= SWD_BOOT_BY_SW_WDOG;
+                       PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
+                       // dump panic will handle saving nvram data
+                       return;
+               }
 
-       if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len) &&
-           !PEReadNVRAMProperty(kIOOSWatchdogFailureString, NULL, &len)) {
-               DLOG("No SleepWake failure or OSWatchdog failure string to read\n");
-               return;
-       }
+               /* Keeping this around for capturing data during power
+                * button press */
 
-       if (len == 0) {
-               DLOG("Ignoring zero byte SleepWake failure string\n");
-               goto exit;
-       }
+               if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
+                       DLOG("No sleep wake failure string\n");
+                       return;
+               }
+               if (len == 0) {
+                       DLOG("Ignoring zero byte SleepWake failure string\n");
+                       goto exit;
+               }
 
-       if (len > sizeof(failureStr)) {
-               len = sizeof(failureStr);
-       }
-       failureStr[0] = 0;
-       if (PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len) == false) {
-               if (PEReadNVRAMProperty(kIOOSWatchdogFailureString, failureStr, &len)) {
-                       oswatchdog = true;
+               // if PMStatus code is zero, delete stackshot and return
+               if (statusCode) {
+                       if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
+                               // there was no sleep wake failure
+                               // this can happen if delete stackshot was called
+                               // before take stackshot completed. Let us delete any
+                               // sleep wake failure data in nvram
+                               DLOG("Deleting stackshot on successful wake\n");
+                               deleteStackshot();
+                               return;
+                       }
+               }
+
+               if (len > sizeof(failureStr)) {
+                       len = sizeof(failureStr);
                }
+               failureStr[0] = 0;
+               PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
        }
        if (failureStr[0] != 0) {
-               error = sleepWakeDebugSaveFile(oswatchdog ? kOSWatchdogFailureStringFile : kSleepWakeFailureStringFile,
-                   failureStr, len);
+               error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
                if (error) {
                        DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
                } else {
                        DLOG("Saved SleepWake failure string to file.\n");
                }
-               if (!oswatchdog) {
-                       swd_flags |= SWD_BOOT_BY_SW_WDOG;
-               }
        }
 
        if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
@@ -9877,8 +11036,17 @@ IOPMrootDomain::saveFailureData2File()
                LOG("Concatenated length for the SWD blob %d\n", concat_len);
 
                if (concat_len) {
-                       error = sleepWakeDebugSaveFile(oswatchdog ? kOSWatchdogStacksFilename : kSleepWakeStacksFilename,
-                           outbuf, concat_len);
+                       error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
+                       if (error) {
+                               LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
+                       } else {
+                               LOG("Saved SleepWake zipped data to file.\n");
+                       }
+               } else {
+                       // There is a sleep wake failure string but no stackshot
+                       // Write a placeholder stacks file so that swd runs
+                       snprintf(outbuf, 20, "%s", "No stackshot data\n");
+                       error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
                        if (error) {
                                LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
                        } else {
@@ -9892,7 +11060,7 @@ IOPMrootDomain::saveFailureData2File()
 
        gRootDomain->swd_lock = 0;
 exit:
-       PERemoveNVRAMProperty(oswatchdog ? kIOOSWatchdogFailureString : kIOSleepWakeFailureString);
+       PERemoveNVRAMProperty(kIOSleepWakeFailureString);
        return;
 }
 
@@ -9952,6 +11120,7 @@ IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen
                        OSKext *kext = OSKext::lookupKextWithAddress((vm_address_t)callMethod);
                        if (kext) {
                                objectName = kext->getIdentifierCString();
+                               kext->release();
                        }
                }
        }
@@ -10136,238 +11305,222 @@ swd_compress(char *inPtr, char *outPtr, size_t numBytes)
 }
 
 void
-IOPMrootDomain::takeStackshot(bool wdogTrigger, bool isOSXWatchdog, bool isSpinDump)
+IOPMrootDomain::deleteStackshot()
 {
-       swd_hdr *         hdr = NULL;
-       int               wdog_panic = -1;
-       int               cnt = 0;
-       pid_t             pid = 0;
-       kern_return_t     kr = KERN_SUCCESS;
-       uint32_t          flags;
+       if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
+               // takeStackshot hasn't completed
+               return;
+       }
+       LOG("Deleting any sleepwake failure data in nvram\n");
 
-       char *            dstAddr;
-       uint32_t          size;
-       uint32_t          bytesRemaining;
-       unsigned          bytesWritten = 0;
-       unsigned          totalBytes = 0;
-       OSString *        UUIDstring = NULL;
+       PERemoveNVRAMProperty(kIOSleepWakeFailureString);
+       char nvram_var_name_buf[20];
+       for (int i = 0; i < 8; i++) {
+               snprintf(nvram_var_name_buf, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
+               if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
+                       LOG("Removing %s returned false\n", nvram_var_name_buf);
+               }
+       }
+       // force NVRAM sync
+       if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, strlen(kIONVRAMSyncNowPropertyKey)) == false) {
+               DLOG("Failed to force nvram sync\n");
+       }
+       gRootDomain->swd_lock = 0;
+}
+void
+IOPMrootDomain::takeStackshot(bool wdogTrigger)
+{
+       swd_hdr *                hdr = NULL;
+       int                      cnt = 0;
+       int                      max_cnt = 2;
+       pid_t                    pid = 0;
+       kern_return_t            kr = KERN_SUCCESS;
+       uint32_t                 flags;
 
-       char              failureStr[512];
-       thread_t          thread = NULL;
-       const char *      uuid;
+       char *                   dstAddr;
+       uint32_t                 size;
+       uint32_t                 bytesRemaining;
+       unsigned                 bytesWritten = 0;
 
+       char                     failureStr[512];
+       thread_t                 thread = NULL;
+       const char *             swfPanic = "swfPanic";
 
-       uint32_t          bufSize;
-       uint32_t          initialStackSize;
 
+       uint32_t                  bufSize;
+       int                       success = 0;
 
+       if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
+               return;
+       }
 
        failureStr[0] = 0;
-       if (isSpinDump) {
-               if (_systemTransitionType != kSystemTransitionSleep &&
-                   _systemTransitionType != kSystemTransitionWake) {
-                       return;
-               }
-
-               if (gSpinDumpBufferFull) {
-                       return;
-               }
-               if (swd_spindump_buffer == NULL) {
-                       sleepWakeDebugSpinDumpMemAlloc();
-                       if (swd_spindump_buffer == NULL) {
-                               return;
-                       }
-               }
-
-               bufSize = SWD_SPINDUMP_SIZE;
-               initialStackSize = SWD_INITIAL_SPINDUMP_SIZE;
-               hdr = (swd_hdr *)swd_spindump_buffer;
-       } else {
-               if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
-                       return;
-               }
+       if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
+               return;
+       }
 
-               if (isOSXWatchdog) {
-                       snprintf(failureStr, sizeof(failureStr), "Stackshot Reason: ");
-                       snprintf(failureStr, sizeof(failureStr), "%smacOS watchdog triggered failure\n", failureStr);
-               } else if (wdogTrigger) {
-                       if ((UUIDstring = OSDynamicCast(OSString, getProperty(kIOPMSleepWakeUUIDKey))) != NULL) {
-                               uuid = UUIDstring->getCStringNoCopy();
-                               snprintf(failureStr, sizeof(failureStr), "UUID: %s\n", uuid);
-                       }
+       if (wdogTrigger) {
+               getFailureData(&thread, failureStr, sizeof(failureStr));
 
-                       snprintf(failureStr, sizeof(failureStr), "%sStackshot Reason: ", failureStr);
-                       getFailureData(&thread, failureStr, sizeof(failureStr));
-                       if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
-                               goto skip_stackshot;
-                       }
-               } else {
-                       snprintf(failureStr, sizeof(failureStr), "%sStackshot triggered for debugging stackshot collection.\n", failureStr);
+               if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
+                       goto skip_stackshot;
                }
-               // Take only one stackshot in this case.
-               cnt = SWD_MAX_STACKSHOTS - 1;
+       } else {
+               AbsoluteTime now;
+               uint64_t nsec;
+               clock_get_uptime(&now);
+               SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
+               absolutetime_to_nanoseconds(now, &nsec);
+               snprintf(failureStr, sizeof(failureStr), "%sPower button pressed during wake transition after %u ms.\n", failureStr, ((int)((nsec) / NSEC_PER_MSEC)));
+       }
 
+       if (swd_buffer == NULL) {
+               sleepWakeDebugMemAlloc();
                if (swd_buffer == NULL) {
-                       sleepWakeDebugMemAlloc();
-                       if (swd_buffer == NULL) {
-                               return;
-                       }
+                       return;
                }
-               hdr = (swd_hdr *)swd_buffer;
-
-               bufSize = hdr->alloc_size;;
-               initialStackSize = bufSize;
        }
+       hdr = (swd_hdr *)swd_buffer;
+       bufSize = hdr->alloc_size;;
 
 
-       if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
-               return;
-       }
 
 
        dstAddr = (char*)hdr + hdr->spindump_offset;
-       bytesRemaining = bufSize - hdr->spindump_offset;
-
-       DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
-
        flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO;
-       while (kr == KERN_SUCCESS) {
-               if (cnt == 0) {
-                       /*
-                        * Take stackshot of all process on first sample. Size is restricted
-                        * to SWD_INITIAL_STACK_SIZE
-                        */
-                       pid = -1;
-                       size = (bytesRemaining > initialStackSize) ? initialStackSize : bytesRemaining;
-               } else {
-                       /* Take sample of kernel threads only */
-                       pid = 0;
-                       size = bytesRemaining;
-               }
+       /* If not wdogTrigger only take kernel tasks stackshot
+        */
+       if (wdogTrigger) {
+               pid = -1;
+       } else {
+               pid = 0;
+       }
+
+       /* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
+        * If we run out of space, take stackshot with only kernel task
+        */
+       while (success == 0 && cnt < max_cnt) {
+               bytesRemaining = bufSize - hdr->spindump_offset;
+               cnt++;
+               DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
 
+               size = bytesRemaining;
                kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, &bytesWritten);
                DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%x bytesWritten: %d\n",
                    kr, pid, size, flags, bytesWritten);
                if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
                        if (pid == -1) {
-                               // Insufficient buffer when trying to take stackshot of user & kernel space threads.
-                               // Continue to take stackshot of just kernel threads
-                               ++cnt;
-                               kr = KERN_SUCCESS;
-                               continue;
-                       } else if (totalBytes == 0) {
-                               MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr, size, flags);
+                               pid = 0;
+                       } else {
+                               LOG("Insufficient buffer size for only kernel task\n");
+                               break;
                        }
                }
+               if (kr == KERN_SUCCESS) {
+                       if (bytesWritten == 0) {
+                               MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%x\n", kr, size, flags);
+                               continue;
+                       }
+                       bytesRemaining -= bytesWritten;
+                       hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
 
-               dstAddr += bytesWritten;
-               totalBytes += bytesWritten;
-               bytesRemaining -= bytesWritten;
-
-               if (++cnt == SWD_MAX_STACKSHOTS) {
-                       break;
-               }
-               IOSleep(10); // 10 ms
-       }
-
-       hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
-
-       memset(hdr->reason, 0x20, sizeof(hdr->reason));
-       if (isSpinDump) {
-               snprintf(hdr->reason, sizeof(hdr->reason), "\nStackshot reason: Power State Change Delay\n\n");
-               gRootDomain->swd_lock = 0;
-               gSpinDumpBufferFull = true;
-               return;
-       }
+                       memset(hdr->reason, 0x20, sizeof(hdr->reason));
 
-       // Compress stackshot and save to NVRAM
-       {
-               char *outbuf = (char *)swd_compressed_buffer;
-               int outlen = 0;
-               int num_chunks = 0;
-               int max_chunks = 0;
-               int leftover = 0;
-               char nvram_var_name_buffer[20];
+                       // Compress stackshot and save to NVRAM
+                       {
+                               char *outbuf = (char *)swd_compressed_buffer;
+                               int outlen = 0;
+                               int num_chunks = 0;
+                               int max_chunks = 0;
+                               int leftover = 0;
+                               char nvram_var_name_buffer[20];
 
-               outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
+                               outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
 
-               if (outlen) {
-                       max_chunks = outlen / (2096 - 200);
-                       leftover = outlen % (2096 - 200);
+                               if (outlen) {
+                                       max_chunks = outlen / (2096 - 200);
+                                       leftover = outlen % (2096 - 200);
 
-                       if (max_chunks < 8) {
-                               for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
-                                       snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
-                                       if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
-                                               LOG("Failed to update NVRAM %d\n", num_chunks);
-                                               break;
-                                       }
-                               }
-                               if (leftover) {
-                                       snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
-                                       if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
-                                               LOG("Failed to update NVRAM with leftovers\n");
+                                       if (max_chunks < 8) {
+                                               for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
+                                                       snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
+                                                       if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
+                                                               LOG("Failed to update NVRAM %d\n", num_chunks);
+                                                               break;
+                                                       }
+                                               }
+                                               if (leftover) {
+                                                       snprintf(nvram_var_name_buffer, 20, "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
+                                                       if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
+                                                               LOG("Failed to update NVRAM with leftovers\n");
+                                                       }
+                                               }
+                                               success = 1;
+                                               LOG("Successfully saved stackshot to NVRAM\n");
+                                       } else {
+                                               LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
+                                               if (pid == -1) {
+                                                       pid = 0;
+                                               } else {
+                                                       LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
+                                                       break;
+                                               }
                                        }
                                }
-                       } else {
-                               LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
                        }
                }
        }
 
        if (failureStr[0]) {
-               if (!isOSXWatchdog) {
-                       // append sleep-wake failure code
-                       snprintf(failureStr, sizeof(failureStr), "%s\nFailure code:: 0x%08x %08x\n",
-                           failureStr, pmTracer->getTraceData(), pmTracer->getTracePhase());
-                       if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, strlen(failureStr)) == false) {
-                               DLOG("Failed to write SleepWake failure string\n");
-                       }
-               } else {
-                       if (PEWriteNVRAMProperty(kIOOSWatchdogFailureString, failureStr, strlen(failureStr)) == false) {
-                               DLOG("Failed to write OSWatchdog failure string\n");
-                       }
+               // append sleep-wake failure code
+               snprintf(failureStr, sizeof(failureStr), "%s\nFailure code:: 0x%08x %08x\n",
+                   failureStr, pmTracer->getTraceData(), pmTracer->getTracePhase());
+               if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, strlen(failureStr)) == false) {
+                       DLOG("Failed to write SleepWake failure string\n");
                }
        }
-       gRootDomain->swd_lock = 0;
+
+       // force NVRAM sync
+       if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, strlen(kIONVRAMSyncNowPropertyKey)) == false) {
+               DLOG("Failed to force nvram sync\n");
+       }
 
 skip_stackshot:
        if (wdogTrigger) {
-               PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic));
-
-               if ((wdog_panic == 1) || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
-                       if (thread) {
-                               panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
-                       } else {
-                               panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
+               if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
+                       if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
+                               // If current boot is due to this watch dog trigger restart in previous boot,
+                               // then don't trigger again until at least 1 successful sleep & wake.
+                               if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
+                                       LOG("Shutting down due to repeated Sleep/Wake failures\n");
+                                       if (!tasksSuspended) {
+                                               tasksSuspended = TRUE;
+                                               updateTasksSuspend();
+                                       }
+                                       PEHaltRestart(kPEHaltCPU);
+                                       return;
+                               }
                        }
-                       return;
-               } else if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
-                       // If current boot is due to this watch dog trigger restart in previous boot,
-                       // then don't trigger again until at least 1 successful sleep & wake.
-                       if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
-                               LOG("Shutting down due to repeated Sleep/Wake failures\n");
+                       if (gSwdPanic == 0) {
+                               LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
                                if (!tasksSuspended) {
                                        tasksSuspended = TRUE;
-                                       tasks_system_suspend(true);
+                                       updateTasksSuspend();
                                }
-                               PEHaltRestart(kPEHaltCPU);
-                               return;
+                               PEHaltRestart(kPERestartCPU);
                        }
                }
-       }
-
-
-       if (wdogTrigger) {
-               LOG("Restarting to collect Sleep wake debug logs\n");
-               if (!tasksSuspended) {
-                       tasksSuspended = TRUE;
-                       tasks_system_suspend(true);
+               if (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, strlen(swfPanic)) == false) {
+                       DLOG("Failed to write SleepWake failure panic key\n");
+               }
+               if (thread) {
+                       panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
+               } else {
+                       panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
                }
-
-               PEHaltRestart(kPERestartCPU);
        } else {
-               saveFailureData2File();
+               gRootDomain->swd_lock = 0;
+               return;
        }
 }
 
@@ -10386,10 +11539,6 @@ IOPMrootDomain::sleepWakeDebugMemAlloc()
                return;
        }
 
-       if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
-               return;
-       }
-
        if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
                return;
        }
@@ -10556,11 +11705,8 @@ exit:
 void
 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
 {
-       uint32_t wdog_panic = 1;
-
        if (restart) {
-               if (PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic)) &&
-                   (wdog_panic == 0)) {
+               if (gSwdPanic == 0) {
                        return;
                }
                panic("Sleep/Wake hang detected");
@@ -10569,12 +11715,14 @@ IOPMrootDomain::sleepWakeDebugTrig(bool restart)
 }
 
 void
-IOPMrootDomain::takeStackshot(bool restart, bool isOSXWatchdog, bool isSpinDump)
+IOPMrootDomain::takeStackshot(bool restart)
 {
 #pragma unused(restart)
-#pragma unused(isOSXWatchdog)
 }
-
+void
+IOPMrootDomain::deleteStackshot()
+{
+}
 void
 IOPMrootDomain::sleepWakeDebugMemAlloc()
 {