xref: /xnu-11417.140.69/iokit/Kernel/IOPMrootDomain.cpp (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 #include <libkern/c++/OSAllocation.h>
32 #include <libkern/c++/OSKext.h>
33 #include <libkern/c++/OSMetaClass.h>
34 #include <libkern/OSAtomic.h>
35 #include <libkern/OSDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommandGate.h>
38 #include <IOKit/IOTimerEventSource.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOCPU.h>
41 #include <IOKit/IOPlatformActions.h>
42 #include <IOKit/IOKitDebug.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
47 #include <IOKit/IODeviceTreeSupport.h>
48 #include <IOKit/IOMessage.h>
49 #include <IOKit/IOReturn.h>
50 #include <IOKit/IONVRAM.h>
51 #include "RootDomainUserClient.h"
52 #include "IOKit/pwr_mgt/IOPowerConnection.h"
53 #include "IOPMPowerStateQueue.h"
54 #include <IOKit/IOCatalogue.h>
55 #include <IOKit/IOReportMacros.h>
56 #include <IOKit/IOLib.h>
57 #include <IOKit/IOKitKeys.h>
58 #include <IOKit/IOUserServer.h>
59 #include "IOKitKernelInternal.h"
60 #if HIBERNATION
61 #include <IOKit/IOHibernatePrivate.h>
62 #endif /* HIBERNATION */
63 #include <machine/machine_routines.h>
64 #include <console/video_console.h>
65 #include <sys/syslog.h>
66 #include <sys/sysctl.h>
67 #include <sys/vnode.h>
68 #include <sys/vnode_internal.h>
69 #include <sys/fcntl.h>
70 #include <os/log.h>
71 #include <pexpert/protos.h>
72 #include <AssertMacros.h>
73 
74 #include <sys/time.h>
75 #include "IOServicePrivate.h"   // _IOServiceInterestNotifier
76 #include "IOServicePMPrivate.h"
77 
78 #include <libkern/zlib.h>
79 #include <os/cpp_util.h>
80 #include <os/atomic_private.h>
81 #include <libkern/c++/OSBoundedArrayRef.h>
82 
83 #if DEVELOPMENT || DEBUG
84 #include <os/system_event_log.h>
85 #endif /* DEVELOPMENT || DEBUG */
86 
87 __BEGIN_DECLS
88 #include <mach/shared_region.h>
89 #include <kern/clock.h>
90 #include <vm/vm_pageout_xnu.h>
91 __END_DECLS
92 
93 #if defined(__i386__) || defined(__x86_64__)
94 __BEGIN_DECLS
95 #include "IOPMrootDomainInternal.h"
96 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
97 __END_DECLS
98 #endif
99 
100 #define kIOPMrootDomainClass    "IOPMrootDomain"
101 #define LOG_PREFIX              "PMRD: "
102 
103 
104 #define MSG(x...) \
105     do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
106 
107 #define LOG(x...)    \
108     do { kprintf(LOG_PREFIX x); } while (false)
109 
110 #if DEVELOPMENT || DEBUG
111 #define DEBUG_LOG(x...) do { \
112     if (kIOLogPMRootDomain & gIOKitDebug) \
113     kprintf(LOG_PREFIX x); \
114     os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
115 } while (false)
116 #else
117 #define DEBUG_LOG(x...)
118 #endif
119 
120 #define DLOG(x...)  do { \
121     if (kIOLogPMRootDomain & gIOKitDebug) \
122 	IOLog(LOG_PREFIX x); \
123     else \
124 	os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
125 } while (false)
126 
127 #define DMSG(x...)  do { \
128     if (kIOLogPMRootDomain & gIOKitDebug) { \
129 	kprintf(LOG_PREFIX x); \
130     } \
131 } while (false)
132 
133 
134 #define _LOG(x...)
135 
136 #define CHECK_THREAD_CONTEXT
137 #ifdef  CHECK_THREAD_CONTEXT
138 static IOWorkLoop * gIOPMWorkLoop = NULL;
139 #define ASSERT_GATED()                                      \
140 do {                                                        \
141     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
142 	panic("RootDomain: not inside PM gate");            \
143     }                                                       \
144 } while(false)
145 #else
146 #define ASSERT_GATED()
147 #endif /* CHECK_THREAD_CONTEXT */
148 
149 #define CAP_LOSS(c)  \
150 	(((_pendingCapability & (c)) == 0) && \
151 	 ((_currentCapability & (c)) != 0))
152 
153 #define CAP_GAIN(c)  \
154 	(((_currentCapability & (c)) == 0) && \
155 	 ((_pendingCapability & (c)) != 0))
156 
157 #define CAP_CHANGE(c)    \
158 	(((_currentCapability ^ _pendingCapability) & (c)) != 0)
159 
160 #define CAP_CURRENT(c)  \
161 	((_currentCapability & (c)) != 0)
162 
163 #define CAP_HIGHEST(c)  \
164 	((_highestCapability & (c)) != 0)
165 
166 #define CAP_PENDING(c)  \
167 	((_pendingCapability & (c)) != 0)
168 
169 // rdar://problem/9157444
170 #if defined(__i386__) || defined(__x86_64__)
171 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY   20
172 #endif
173 
174 // Event types for IOPMPowerStateQueue::submitPowerEvent()
175 enum {
176 	kPowerEventFeatureChanged = 1,             // 1
177 	kPowerEventReceivedPowerNotification,      // 2
178 	kPowerEventSystemBootCompleted,            // 3
179 	kPowerEventSystemShutdown,                 // 4
180 	kPowerEventUserDisabledSleep,              // 5
181 	kPowerEventRegisterSystemCapabilityClient, // 6
182 	kPowerEventRegisterKernelCapabilityClient, // 7
183 	kPowerEventPolicyStimulus,                 // 8
184 	kPowerEventAssertionCreate,                // 9
185 	kPowerEventAssertionRelease,               // 10
186 	kPowerEventAssertionSetLevel,              // 11
187 	kPowerEventQueueSleepWakeUUID,             // 12
188 	kPowerEventPublishSleepWakeUUID,           // 13
189 	kPowerEventSetDisplayPowerOn,              // 14
190 	kPowerEventPublishWakeType,                // 15
191 	kPowerEventAOTEvaluate                     // 16
192 };
193 
194 // For evaluatePolicy()
195 // List of stimuli that affects the root domain policy.
196 enum {
197 	kStimulusDisplayWranglerSleep,      // 0
198 	kStimulusDisplayWranglerWake,       // 1
199 	kStimulusAggressivenessChanged,     // 2
200 	kStimulusDemandSystemSleep,         // 3
201 	kStimulusAllowSystemSleepChanged,   // 4
202 	kStimulusDarkWakeActivityTickle,    // 5
203 	kStimulusDarkWakeEntry,             // 6
204 	kStimulusDarkWakeReentry,           // 7
205 	kStimulusDarkWakeEvaluate,          // 8
206 	kStimulusNoIdleSleepPreventers,     // 9
207 	kStimulusEnterUserActiveState,      // 10
208 	kStimulusLeaveUserActiveState       // 11
209 };
210 
211 // Internal power state change reasons
212 // Must be less than kIOPMSleepReasonClamshell=101
213 enum {
214 	kCPSReasonNone = 0,                 // 0
215 	kCPSReasonInit,                     // 1
216 	kCPSReasonWake,                     // 2
217 	kCPSReasonIdleSleepPrevent,         // 3
218 	kCPSReasonIdleSleepAllow,           // 4
219 	kCPSReasonPowerOverride,            // 5
220 	kCPSReasonPowerDownCancel,          // 6
221 	kCPSReasonAOTExit,                  // 7
222 	kCPSReasonAdjustPowerState,         // 8
223 	kCPSReasonDarkWakeCannotSleep,      // 9
224 	kCPSReasonIdleSleepEnabled,         // 10
225 	kCPSReasonEvaluatePolicy,           // 11
226 	kCPSReasonSustainFullWake,          // 12
227 	kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
228 };
229 
230 extern "C" {
231 IOReturn OSKextSystemSleepOrWake( UInt32 );
232 }
233 extern "C" ppnum_t      pmap_find_phys(pmap_t pmap, addr64_t va);
234 extern "C" addr64_t     kvtophys(vm_offset_t va);
235 extern "C" boolean_t    kdp_has_polled_corefile();
236 
237 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
238 static void notifySystemShutdown( IOService * root, uint32_t messageType );
239 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
240 static void pmEventTimeStamp(uint64_t *recordTS);
241 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
242 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
243 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
244 
245 static int  IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
246 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
247 #define YMDTF       "%04d/%02d/%d %02d:%02d:%02d"
248 #define YMDT(cal)   ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
249 
250 // "IOPMSetSleepSupported"  callPlatformFunction name
251 static OSSharedPtr<const OSSymbol>         sleepSupportedPEFunction;
252 static OSSharedPtr<const OSSymbol>         sleepMessagePEFunction;
253 static OSSharedPtr<const OSSymbol>         gIOPMWakeTypeUserKey;
254 
255 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalConnectedKey;
256 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalChargeCapableKey;
257 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryInstalledKey;
258 static OSSharedPtr<const OSSymbol>         gIOPMPSIsChargingKey;
259 static OSSharedPtr<const OSSymbol>         gIOPMPSAtWarnLevelKey;
260 static OSSharedPtr<const OSSymbol>         gIOPMPSAtCriticalLevelKey;
261 static OSSharedPtr<const OSSymbol>         gIOPMPSCurrentCapacityKey;
262 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxCapacityKey;
263 static OSSharedPtr<const OSSymbol>         gIOPMPSDesignCapacityKey;
264 static OSSharedPtr<const OSSymbol>         gIOPMPSTimeRemainingKey;
265 static OSSharedPtr<const OSSymbol>         gIOPMPSAmperageKey;
266 static OSSharedPtr<const OSSymbol>         gIOPMPSVoltageKey;
267 static OSSharedPtr<const OSSymbol>         gIOPMPSCycleCountKey;
268 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxErrKey;
269 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterInfoKey;
270 static OSSharedPtr<const OSSymbol>         gIOPMPSLocationKey;
271 static OSSharedPtr<const OSSymbol>         gIOPMPSErrorConditionKey;
272 static OSSharedPtr<const OSSymbol>         gIOPMPSManufacturerKey;
273 static OSSharedPtr<const OSSymbol>         gIOPMPSManufactureDateKey;
274 static OSSharedPtr<const OSSymbol>         gIOPMPSModelKey;
275 static OSSharedPtr<const OSSymbol>         gIOPMPSSerialKey;
276 static OSSharedPtr<const OSSymbol>         gIOPMPSLegacyBatteryInfoKey;
277 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryHealthKey;
278 static OSSharedPtr<const OSSymbol>         gIOPMPSHealthConfidenceKey;
279 static OSSharedPtr<const OSSymbol>         gIOPMPSCapacityEstimatedKey;
280 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryChargeStatusKey;
281 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryTemperatureKey;
282 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsKey;
283 static OSSharedPtr<const OSSymbol>         gIOPMPSChargerConfigurationKey;
284 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsIDKey;
285 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsWattsKey;
286 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsRevisionKey;
287 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSerialNumberKey;
288 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsFamilyKey;
289 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsAmperageKey;
290 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsDescriptionKey;
291 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsPMUConfigurationKey;
292 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSourceIDKey;
293 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsErrorFlagsKey;
294 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSharedSourceKey;
295 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsCloakedKey;
296 static OSSharedPtr<const OSSymbol>         gIOPMPSInvalidWakeSecondsKey;
297 static OSSharedPtr<const OSSymbol>         gIOPMPSPostChargeWaitSecondsKey;
298 static OSSharedPtr<const OSSymbol>         gIOPMPSPostDishargeWaitSecondsKey;
299 
300 #define kIOSleepSupportedKey        "IOSleepSupported"
301 #define kIOPMSystemCapabilitiesKey  "System Capabilities"
302 #define kIOPMSystemDefaultOverrideKey   "SystemPowerProfileOverrideDict"
303 
304 #define kIORequestWranglerIdleKey   "IORequestIdle"
305 #define kDefaultWranglerIdlePeriod  1000 // in milliseconds
306 
307 #define kIOSleepWakeFailureString   "SleepWakeFailureString"
308 #define kIOEFIBootRomFailureKey     "wake-failure"
309 #define kIOSleepWakeFailurePanic    "SleepWakeFailurePanic"
310 
311 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
312 	                   | kIOPMSupportedOnBatt \
313 	                   | kIOPMSupportedOnUPS)
314 
315 #define kLocalEvalClamshellCommand  (1 << 15)
316 #define kIdleSleepRetryInterval     (3 * 60 * 1000)
317 
318 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
319 // We impose this minimum to avoid race conditions in the AP wake path where
320 // userspace clients are not able to acquire power assertions before the idle timer expires.
321 #if XNU_TARGET_OS_IOS
322 #define kMinimumTimeBeforeIdleSleep     3000
323 #else
324 #define kMinimumTimeBeforeIdleSleep     1000
325 #endif
326 
327 #define DISPLAY_WRANGLER_PRESENT    (!NO_KERNEL_HID)
328 
329 enum {
330 	kWranglerPowerStateMin   = 0,
331 	kWranglerPowerStateSleep = 2,
332 	kWranglerPowerStateDim   = 3,
333 	kWranglerPowerStateMax   = 4
334 };
335 
336 enum {
337 	OFF_STATE           = 0,
338 	RESTART_STATE       = 1,
339 	SLEEP_STATE         = 2,
340 	AOT_STATE           = 3,
341 	ON_STATE            = 4,
342 	NUM_POWER_STATES
343 };
344 
345 const char *
getPowerStateString(uint32_t state)346 getPowerStateString( uint32_t state )
347 {
348 #define POWER_STATE(x) {(uint32_t) x, #x}
349 
350 	static const IONamedValue powerStates[] = {
351 		POWER_STATE( OFF_STATE ),
352 		POWER_STATE( RESTART_STATE ),
353 		POWER_STATE( SLEEP_STATE ),
354 		POWER_STATE( AOT_STATE ),
355 		POWER_STATE( ON_STATE ),
356 		{ 0, NULL }
357 	};
358 	return IOFindNameForValue(state, powerStates);
359 }
360 
361 #define ON_POWER        kIOPMPowerOn
362 #define RESTART_POWER   kIOPMRestart
363 #define SLEEP_POWER     kIOPMAuxPowerOn
364 
365 static IOPMPowerState
366     ourPowerStates[NUM_POWER_STATES] =
367 {
368 	{   .version                = 1,
369 	    .capabilityFlags        = 0,
370 	    .outputPowerCharacter   = 0,
371 	    .inputPowerRequirement  = 0 },
372 	{   .version                = 1,
373 	    .capabilityFlags        = kIOPMRestartCapability,
374 	    .outputPowerCharacter   = kIOPMRestart,
375 	    .inputPowerRequirement  = RESTART_POWER },
376 	{   .version                = 1,
377 	    .capabilityFlags        = kIOPMSleepCapability,
378 	    .outputPowerCharacter   = kIOPMSleep,
379 	    .inputPowerRequirement  = SLEEP_POWER },
380 	{   .version                = 1,
381 	    .capabilityFlags        = kIOPMAOTCapability,
382 	    .outputPowerCharacter   = kIOPMAOTPower,
383 	    .inputPowerRequirement  = ON_POWER },
384 	{   .version                = 1,
385 	    .capabilityFlags        = kIOPMPowerOn,
386 	    .outputPowerCharacter   = kIOPMPowerOn,
387 	    .inputPowerRequirement  = ON_POWER },
388 };
389 
390 #define kIOPMRootDomainWakeTypeSleepService     "SleepService"
391 #define kIOPMRootDomainWakeTypeMaintenance      "Maintenance"
392 #define kIOPMRootDomainWakeTypeSleepTimer       "SleepTimer"
393 #define kIOPMrootDomainWakeTypeLowBattery       "LowBattery"
394 #define kIOPMRootDomainWakeTypeUser             "User"
395 #define kIOPMRootDomainWakeTypeAlarm            "Alarm"
396 #define kIOPMRootDomainWakeTypeNetwork          "Network"
397 #define kIOPMRootDomainWakeTypeHIDActivity      "HID Activity"
398 #define kIOPMRootDomainWakeTypeNotification     "Notification"
399 #define kIOPMRootDomainWakeTypeHibernateError   "HibernateError"
400 
401 // Special interest that entitles the interested client from receiving
402 // all system messages. Only used by powerd.
403 //
404 #define kIOPMSystemCapabilityInterest       "IOPMSystemCapabilityInterest"
405 
406 // Entitlement required for root domain clients
407 #define kRootDomainEntitlementSetProperty   "com.apple.private.iokit.rootdomain-set-property"
408 
409 #define WAKEEVENT_LOCK()        IOLockLock(wakeEventLock)
410 #define WAKEEVENT_UNLOCK()      IOLockUnlock(wakeEventLock)
411 
412 /*
413  * Aggressiveness
414  */
415 #define AGGRESSIVES_LOCK()      IOLockLock(featuresDictLock)
416 #define AGGRESSIVES_UNLOCK()    IOLockUnlock(featuresDictLock)
417 
418 #define kAggressivesMinValue    1
419 
420 const char *
getAggressivenessTypeString(uint32_t type)421 getAggressivenessTypeString( uint32_t type )
422 {
423 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
424 
425 	static const IONamedValue aggressivenessTypes[] = {
426 		AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
427 		AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
428 		AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
429 		AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
430 		AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
431 		AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
432 		AGGRESSIVENESS_TYPE( kPMPowerSource),
433 		AGGRESSIVENESS_TYPE( kPMMotionSensor ),
434 		AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
435 		{ 0, NULL }
436 	};
437 	return IOFindNameForValue(type, aggressivenessTypes);
438 }
439 
440 enum {
441 	kAggressivesStateBusy           = 0x01,
442 	kAggressivesStateQuickSpindown  = 0x02
443 };
444 
445 struct AggressivesRecord {
446 	uint32_t    flags;
447 	uint32_t    type;
448 	uint32_t    value;
449 };
450 
451 struct AggressivesRequest {
452 	queue_chain_t           chain;
453 	uint32_t                options;
454 	uint32_t                dataType;
455 	union {
456 		OSSharedPtr<IOService> service;
457 		AggressivesRecord      record;
458 	} data;
459 };
460 
461 enum {
462 	kAggressivesRequestTypeService  = 1,
463 	kAggressivesRequestTypeRecord
464 };
465 
466 enum {
467 	kAggressivesOptionSynchronous          = 0x00000001,
468 	kAggressivesOptionQuickSpindownEnable  = 0x00000100,
469 	kAggressivesOptionQuickSpindownDisable = 0x00000200,
470 	kAggressivesOptionQuickSpindownMask    = 0x00000300
471 };
472 
473 enum {
474 	kAggressivesRecordFlagModified         = 0x00000001,
475 	kAggressivesRecordFlagMinValue         = 0x00000002
476 };
477 
478 // System Sleep Preventers
479 
480 enum {
481 	kPMUserDisabledAllSleep = 1,
482 	kPMSystemRestartBootingInProgress,
483 	kPMConfigPreventSystemSleep,
484 	kPMChildPreventSystemSleep,
485 	kPMCPUAssertion,
486 	kPMPCIUnsupported,
487 	kPMDKNotReady,
488 };
489 
490 const char *
getSystemSleepPreventerString(uint32_t preventer)491 getSystemSleepPreventerString( uint32_t preventer )
492 {
493 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
494 	static const IONamedValue systemSleepPreventers[] = {
495 		SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
496 		SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
497 		SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
498 		SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
499 		SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
500 		SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
501 		SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
502 		{ 0, NULL }
503 	};
504 	return IOFindNameForValue(preventer, systemSleepPreventers);
505 }
506 
507 // gDarkWakeFlags
508 enum {
509 	kDarkWakeFlagPromotionNone       = 0x0000,
510 	kDarkWakeFlagPromotionEarly      = 0x0001, // promote before gfx clamp
511 	kDarkWakeFlagPromotionLate       = 0x0002, // promote after gfx clamp
512 	kDarkWakeFlagPromotionMask       = 0x0003,
513 	kDarkWakeFlagAlarmIsDark         = 0x0100,
514 	kDarkWakeFlagAudioNotSuppressed  = 0x0200,
515 	kDarkWakeFlagUserWakeWorkaround  = 0x1000
516 };
517 
518 // gClamshellFlags
519 // The workaround for 9157444 is enabled at compile time using the
520 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
521 enum {
522 	kClamshell_WAR_38378787 = 0x00000001,
523 	kClamshell_WAR_47715679 = 0x00000002,
524 	kClamshell_WAR_58009435 = 0x00000004
525 };
526 
527 // acceptSystemWakeEvents()
528 enum {
529 	kAcceptSystemWakeEvents_Disable = 0,
530 	kAcceptSystemWakeEvents_Enable,
531 	kAcceptSystemWakeEvents_Reenable
532 };
533 
534 static IOPMrootDomain * gRootDomain;
535 static IORootParent *   gPatriarch;
536 static IONotifier *     gSysPowerDownNotifier = NULL;
537 static UInt32           gSleepOrShutdownPending = 0;
538 static UInt32           gWillShutdown = 0;
539 static UInt32           gPagingOff = 0;
540 static UInt32           gSleepWakeUUIDIsSet = false;
541 static uint32_t         gAggressivesState = 0;
542 uint32_t                gHaltTimeMaxLog;
543 uint32_t                gHaltTimeMaxPanic;
544 IOLock *                gHaltLogLock;
545 static char *           gHaltLog;
546 enum                  { kHaltLogSize = 2048 };
547 static size_t           gHaltLogPos;
548 static uint64_t         gHaltStartTime;
549 static char             gKextNameBuf[64];
550 static size_t           gKextNamePos;
551 static bool             gKextNameEnd;
552 
553 uuid_string_t bootsessionuuid_string;
554 
555 #if defined(XNU_TARGET_OS_OSX)
556 #if DISPLAY_WRANGLER_PRESENT
557 static uint32_t         gDarkWakeFlags = kDarkWakeFlagPromotionNone;
558 #elif defined(__arm64__)
559 // Enable temporary full wake promotion workarounds
560 static uint32_t         gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
561 #else
562 // Enable full wake promotion workarounds
563 static uint32_t         gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
564 #endif
565 #else  /* !defined(XNU_TARGET_OS_OSX) */
566 static uint32_t         gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
567 #endif /* !defined(XNU_TARGET_OS_OSX) */
568 
569 static uint32_t         gNoIdleFlag = 0;
570 static uint32_t         gSleepDisabledFlag = 0;
571 static uint32_t         gSwdPanic = 1;
572 static uint32_t         gSwdSleepTimeout = 0;
573 static uint32_t         gSwdWakeTimeout = 0;
574 static uint32_t         gSwdSleepWakeTimeout = 0;
575 static PMStatsStruct    gPMStats;
576 #if DEVELOPMENT || DEBUG
577 static uint32_t swd_panic_phase;
578 #endif
579 
580 static uint32_t         gClamshellFlags = 0
581 #if defined(__i386__) || defined(__x86_64__)
582     | kClamshell_WAR_58009435
583 #endif
584 ;
585 
586 #if HIBERNATION
587 
588 #if defined(__arm64__)
589 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)590 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
591 {
592 	uint32_t sleepType = kIOPMSleepTypeDeepIdle;
593 
594 	assert(vars->signature == kIOPMSystemSleepPolicySignature);
595 	assert(vars->version == kIOPMSystemSleepPolicyVersion);
596 
597 	// Hibernation enabled and either user forced hibernate or low battery sleep
598 	if ((vars->hibernateMode & kIOHibernateModeOn) &&
599 	    (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
600 	    (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
601 		sleepType = kIOPMSleepTypeHibernate;
602 	}
603 	params->version = kIOPMSystemSleepParametersVersion;
604 	params->sleepType = sleepType;
605 	return kIOReturnSuccess;
606 }
607 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = &defaultSleepPolicyHandler;
608 #else /* defined(__arm64__) */
609 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = NULL;
610 #endif /* defined(__arm64__) */
611 
612 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
613 static void *                           gSleepPolicyTarget;
614 #endif
615 
616 struct timeval gIOLastSleepTime;
617 struct timeval gIOLastWakeTime;
618 AbsoluteTime gIOLastWakeAbsTime;
619 AbsoluteTime gIOLastSleepAbsTime;
620 
621 struct timeval gIOLastUserSleepTime;
622 
623 static char gWakeReasonString[128];
624 static char gBootReasonString[80];
625 static char gShutdownReasonString[80];
626 static bool gWakeReasonSysctlRegistered = false;
627 static bool gBootReasonSysctlRegistered = false;
628 static bool gShutdownReasonSysctlRegistered = false;
629 static bool gWillShutdownSysctlRegistered = false;
630 static AbsoluteTime gUserActiveAbsTime;
631 static AbsoluteTime gUserInactiveAbsTime;
632 
633 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
634 static bool gSpinDumpBufferFull = false;
635 #endif
636 
637 z_stream          swd_zs;
638 vm_offset_t swd_zs_zmem;
639 //size_t swd_zs_zsize;
640 size_t swd_zs_zoffset;
641 #if defined(__i386__) || defined(__x86_64__)
642 IOCPU *currentShutdownTarget = NULL;
643 #endif
644 
645 static unsigned int     gPMHaltBusyCount;
646 static unsigned int     gPMHaltIdleCount;
647 static int              gPMHaltDepth;
648 static uint32_t         gPMHaltMessageType;
649 static IOLock *         gPMHaltLock  = NULL;
650 static OSSharedPtr<OSArray>        gPMHaltArray;
651 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
652 static bool             gPMQuiesced;
653 
654 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
655 #define kCPUUnknownIndex    9999999
656 enum {
657 	kInformAC = 0,
658 	kInformLid = 1,
659 	kInformableCount = 2
660 };
661 
662 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
663 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
664 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
665 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
666 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
667 
668 #define kBadPMFeatureID     0
669 
670 /*
671  * PMSettingHandle
672  * Opaque handle passed to clients of registerPMSettingController()
673  */
674 class PMSettingHandle : public OSObject
675 {
676 	OSDeclareFinalStructors( PMSettingHandle );
677 	friend class PMSettingObject;
678 
679 private:
680 	PMSettingObject *pmso;
681 	void free(void) APPLE_KEXT_OVERRIDE;
682 };
683 
684 /*
685  * PMSettingObject
686  * Internal object to track each PM setting controller
687  */
688 class PMSettingObject : public OSObject
689 {
690 	OSDeclareFinalStructors( PMSettingObject );
691 	friend class IOPMrootDomain;
692 
693 private:
694 	queue_head_t                    calloutQueue;
695 	thread_t                        waitThread;
696 	IOPMrootDomain                  *parent;
697 	PMSettingHandle                 *pmsh;
698 	IOPMSettingControllerCallback   func;
699 	OSObject                        *target;
700 	uintptr_t                       refcon;
701 	OSDataAllocation<uint32_t>      publishedFeatureID;
702 	uint32_t                        settingCount;
703 	bool                            disabled;
704 
705 	void free(void) APPLE_KEXT_OVERRIDE;
706 
707 public:
708 	static PMSettingObject *pmSettingObject(
709 		IOPMrootDomain                  *parent_arg,
710 		IOPMSettingControllerCallback   handler_arg,
711 		OSObject                        *target_arg,
712 		uintptr_t                       refcon_arg,
713 		uint32_t                        supportedPowerSources,
714 		const OSSymbol                  *settings[],
715 		OSObject                        **handle_obj);
716 
717 	IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
718 	void clientHandleFreed(void);
719 };
720 
721 struct PMSettingCallEntry {
722 	queue_chain_t   link;
723 	thread_t        thread;
724 };
725 
726 #define PMSETTING_LOCK()    IOLockLock(settingsCtrlLock)
727 #define PMSETTING_UNLOCK()  IOLockUnlock(settingsCtrlLock)
728 #define PMSETTING_WAIT(p)   IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
729 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
730 
731 /*
732  * PMTraceWorker
733  * Internal helper object for logging trace points to RTC
734  * IOPMrootDomain and only IOPMrootDomain should instantiate
735  * exactly one of these.
736  */
737 
738 typedef void (*IOPMTracePointHandler)(
739 	void * target, uint32_t code, uint32_t data );
740 
741 class PMTraceWorker : public OSObject
742 {
743 	OSDeclareDefaultStructors(PMTraceWorker);
744 public:
745 	typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
746 
747 	static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
748 	void                        tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
749 	void                        tracePoint(uint8_t phase);
750 	void                        traceDetail(uint32_t detail);
751 	void                        traceComponentWakeProgress(uint32_t component, uint32_t data);
752 	int                         recordTopLevelPCIDevice(IOService *);
753 	void                        RTC_TRACE(void);
754 	virtual bool                serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
755 
756 	IOPMTracePointHandler       tracePointHandler;
757 	void *                      tracePointTarget;
758 	uint64_t                    getPMStatusCode();
759 	uint8_t                     getTracePhase();
760 	uint32_t                    getTraceData();
761 private:
762 	IOPMrootDomain              *owner;
763 	IOLock                      *pmTraceWorkerLock;
764 	OSSharedPtr<OSArray>         pciDeviceBitMappings;
765 
766 	uint8_t                     addedToRegistry;
767 	uint8_t                     tracePhase;
768 	uint32_t                    traceData32;
769 	uint8_t                     loginWindowData;
770 	uint8_t                     coreDisplayData;
771 	uint8_t                     coreGraphicsData;
772 };
773 
774 /*
775  * this should be treated as POD, as it's byte-copied around
776  * and we cannot rely on d'tor firing at the right time
777  */
778 struct PMAssertStruct {
779 	IOPMDriverAssertionID       id;
780 	IOPMDriverAssertionType     assertionBits;
781 	uint64_t                    createdTime;
782 	uint64_t                    modifiedTime;
783 	const OSSymbol              *ownerString;
784 	IOService                   *ownerService;
785 	uint64_t                    registryEntryID;
786 	IOPMDriverAssertionLevel    level;
787 	uint64_t                    assertCPUStartTime;
788 	uint64_t                    assertCPUDuration;
789 };
790 OSDefineValueObjectForDependentType(PMAssertStruct)
791 
792 /*
793  * PMAssertionsTracker
794  * Tracks kernel and user space PM assertions
795  */
796 class PMAssertionsTracker : public OSObject
797 {
798 	OSDeclareFinalStructors(PMAssertionsTracker);
799 public:
800 	static PMAssertionsTracker  *pmAssertionsTracker( IOPMrootDomain * );
801 
802 	IOReturn                    createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
803 	IOReturn                    releaseAssertion(IOPMDriverAssertionID);
804 	IOReturn                    setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
805 	IOReturn                    setUserAssertionLevels(IOPMDriverAssertionType);
806 
807 	OSSharedPtr<OSArray>        copyAssertionsArray(void);
808 	IOPMDriverAssertionType     getActivatedAssertions(void);
809 	IOPMDriverAssertionLevel    getAssertionLevel(IOPMDriverAssertionType);
810 
811 	IOReturn                    handleCreateAssertion(OSValueObject<PMAssertStruct> *);
812 	IOReturn                    handleReleaseAssertion(IOPMDriverAssertionID);
813 	IOReturn                    handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
814 	IOReturn                    handleSetUserAssertionLevels(void * arg0);
815 	void                        publishProperties(void);
816 	void                        reportCPUBitAccounting(void);
817 	PMAssertStruct              *detailsForID(IOPMDriverAssertionID, int *);
818 
819 private:
820 	uint32_t                    tabulateProducerCount;
821 	uint32_t                    tabulateConsumerCount;
822 
823 	uint64_t                    maxAssertCPUDuration;
824 	uint64_t                    maxAssertCPUEntryId;
825 
826 	void                        tabulate(void);
827 	void                        updateCPUBitAccounting(PMAssertStruct * assertStruct);
828 
829 	IOPMrootDomain              *owner;
830 	OSSharedPtr<OSArray>        assertionsArray;
831 	IOLock                      *assertionsArrayLock;
832 	IOPMDriverAssertionID       issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
833 	IOPMDriverAssertionType     assertionsKernel;
834 	IOPMDriverAssertionType     assertionsUser;
835 	IOPMDriverAssertionType     assertionsCombined;
836 };
837 
838 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
839 
840 /*
841  * PMHaltWorker
842  * Internal helper object for Shutdown/Restart notifications.
843  */
844 #define kPMHaltMaxWorkers   8
845 #define kPMHaltTimeoutMS    100
846 
847 class PMHaltWorker : public OSObject
848 {
849 	OSDeclareFinalStructors( PMHaltWorker );
850 
851 public:
852 	IOService *  service;// service being worked on
853 	AbsoluteTime startTime; // time when work started
854 	int          depth;  // work on nubs at this PM-tree depth
855 	int          visits; // number of nodes visited (debug)
856 	IOLock *     lock;
857 	bool         timeout;// service took too long
858 
859 	static  PMHaltWorker * worker( void );
860 	static  void main( void * arg, wait_result_t waitResult );
861 	static  void work( PMHaltWorker * me );
862 	static  void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
863 	virtual void free( void ) APPLE_KEXT_OVERRIDE;
864 };
865 
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)866 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
867 
868 
869 #define super IOService
870 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
871 
872 boolean_t
873 IOPMRootDomainGetWillShutdown(void)
874 {
875 	return gWillShutdown != 0;
876 }
877 
878 static void
IOPMRootDomainWillShutdown(void)879 IOPMRootDomainWillShutdown(void)
880 {
881 	if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
882 		IOService::willShutdown();
883 		for (int i = 0; i < 100; i++) {
884 			if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
885 				break;
886 			}
887 			IOSleep( 100 );
888 		}
889 	}
890 }
891 
892 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)893 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
894 {
895 	return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
896 }
897 
898 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)899 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
900 {
901 	return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
902 }
903 
904 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)905 acknowledgeSleepWakeNotification(void * PMrefcon)
906 {
907 	return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
908 }
909 
910 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)911 vetoSleepWakeNotification(void * PMrefcon)
912 {
913 	return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
914 }
915 
916 extern "C" IOReturn
rootDomainRestart(void)917 rootDomainRestart( void )
918 {
919 	return gRootDomain->restartSystem();
920 }
921 
922 extern "C" IOReturn
rootDomainShutdown(void)923 rootDomainShutdown( void )
924 {
925 	return gRootDomain->shutdownSystem();
926 }
927 
928 static void
halt_log_putc(char c)929 halt_log_putc(char c)
930 {
931 	if (gHaltLogPos >= (kHaltLogSize - 2)) {
932 		return;
933 	}
934 	gHaltLog[gHaltLogPos++] = c;
935 }
936 
937 extern "C" void
938 _doprnt_log(const char     *fmt,
939     va_list                 *argp,
940     void                    (*putc)(char),
941     int                     radix);
942 
943 static int
halt_log(const char * fmt,...)944 halt_log(const char *fmt, ...)
945 {
946 	va_list listp;
947 
948 	va_start(listp, fmt);
949 	_doprnt_log(fmt, &listp, &halt_log_putc, 16);
950 	va_end(listp);
951 
952 	return 0;
953 }
954 
955 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)956 halt_log_enter(const char * what, const void * pc, uint64_t time)
957 {
958 	uint64_t nano, millis;
959 
960 	if (!gHaltLog) {
961 		return;
962 	}
963 	absolutetime_to_nanoseconds(time, &nano);
964 	millis = nano / NSEC_PER_MSEC;
965 	if (millis < 100) {
966 		return;
967 	}
968 
969 	IOLockLock(gHaltLogLock);
970 	if (pc) {
971 		halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
972 		OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
973 		    OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
974 	} else {
975 		halt_log("%s: %qd ms\n", what, millis);
976 	}
977 
978 	gHaltLog[gHaltLogPos] = 0;
979 	IOLockUnlock(gHaltLogLock);
980 }
981 
982 extern  uint32_t                           gFSState;
983 
984 extern "C" void
IOSystemShutdownNotification(int howto,int stage)985 IOSystemShutdownNotification(int howto, int stage)
986 {
987 	uint64_t startTime;
988 
989 	if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
990 #if defined(XNU_TARGET_OS_OSX)
991 		uint64_t nano, millis;
992 		startTime = mach_absolute_time();
993 		IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
994 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
995 		millis = nano / NSEC_PER_MSEC;
996 		if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
997 			printf("waitQuiet() for unmount %qd ms\n", millis);
998 		}
999 #endif /* defined(XNU_TARGET_OS_OSX) */
1000 		return;
1001 	}
1002 
1003 	if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
1004 		uint64_t nano, millis;
1005 		startTime = mach_absolute_time();
1006 		IOServicePH::systemHalt(howto);
1007 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1008 		millis = nano / NSEC_PER_MSEC;
1009 		if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1010 			printf("IOServicePH::systemHalt took %qd ms\n", millis);
1011 		}
1012 		return;
1013 	}
1014 
1015 	assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1016 
1017 	IOLockLock(gHaltLogLock);
1018 	if (!gHaltLog) {
1019 		gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1020 		gHaltStartTime = mach_absolute_time();
1021 		if (gHaltLog) {
1022 			halt_log_putc('\n');
1023 		}
1024 	}
1025 	IOLockUnlock(gHaltLogLock);
1026 
1027 	startTime = mach_absolute_time();
1028 	IOPMRootDomainWillShutdown();
1029 	halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1030 #if HIBERNATION
1031 	startTime = mach_absolute_time();
1032 	IOHibernateSystemPostWake(true);
1033 	halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1034 #endif
1035 	if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1036 		gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1037 	}
1038 }
1039 
1040 extern "C" int sync_internal(void);
1041 
1042 /*
1043  *  A device is always in the highest power state which satisfies its driver,
1044  *  its policy-maker, and any power children it has, but within the constraint
1045  *  of the power state provided by its parent.  The driver expresses its desire by
1046  *  calling changePowerStateTo(), the policy-maker expresses its desire by calling
1047  *  changePowerStateToPriv(), and the children express their desires by calling
1048  *  requestPowerDomainState().
1049  *
1050  *  The Root Power Domain owns the policy for idle and demand sleep for the system.
1051  *  It is a power-managed IOService just like the others in the system.
1052  *  It implements several power states which map to what we see as Sleep and On.
1053  *
1054  *  The sleep policy is as follows:
1055  *  1. Sleep is prevented if the case is open so that nobody will think the machine
1056  *  is off and plug/unplug cards.
1057  *  2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1058  *  3. System cannot Sleep if some object in the tree is in a power state marked
1059  *  kIOPMPreventSystemSleep.
1060  *
1061  *  These three conditions are enforced using the "driver clamp" by calling
1062  *  changePowerStateTo(). For example, if the case is opened,
1063  *  changePowerStateTo(ON_STATE) is called to hold the system on regardless
1064  *  of the desires of the children of the root or the state of the other clamp.
1065  *
1066  *  Demand Sleep is initiated by pressing the front panel power button, closing
1067  *  the clamshell, or selecting the menu item. In this case the root's parent
1068  *  actually initiates the power state change so that the root domain has no
1069  *  choice and does not give applications the opportunity to veto the change.
1070  *
1071  *  Idle Sleep occurs if no objects in the tree are in a state marked
1072  *  kIOPMPreventIdleSleep.  When this is true, the root's children are not holding
1073  *  the root on, so it sets the "policy-maker clamp" by calling
1074  *  changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1075  *  This timer is set for the difference between the sleep timeout slider and the
1076  *  display dim timeout slider. When the timer expires, it releases its clamp and
1077  *  now nothing is holding it awake, so it falls asleep.
1078  *
1079  *  Demand sleep is prevented when the system is booting.  When preferences are
1080  *  transmitted by the loginwindow at the end of boot, a flag is cleared,
1081  *  and this allows subsequent Demand Sleep.
1082  */
1083 
1084 //******************************************************************************
1085 
1086 IOPMrootDomain *
construct(void)1087 IOPMrootDomain::construct( void )
1088 {
1089 	IOPMrootDomain  *root;
1090 
1091 	root = new IOPMrootDomain;
1092 	if (root) {
1093 		root->init();
1094 	}
1095 
1096 	return root;
1097 }
1098 
1099 //******************************************************************************
1100 // updateConsoleUsersCallout
1101 //
1102 //******************************************************************************
1103 
1104 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1105 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1106 {
1107 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1108 	rootDomain->updateConsoleUsers();
1109 }
1110 
1111 void
updateConsoleUsers(void)1112 IOPMrootDomain::updateConsoleUsers(void)
1113 {
1114 	IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1115 	updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1116 }
1117 
1118 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1119 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1120 {
1121 	bool newSuspend;
1122 
1123 	WAKEEVENT_LOCK();
1124 	if (newTasksSuspended != kTasksSuspendNoChange) {
1125 		tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1126 	}
1127 	if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1128 		_aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1129 	}
1130 	newSuspend = (tasksSuspended || _aotTasksSuspended);
1131 	if (newSuspend == tasksSuspendState) {
1132 		WAKEEVENT_UNLOCK();
1133 		return false;
1134 	}
1135 	tasksSuspendState = newSuspend;
1136 	WAKEEVENT_UNLOCK();
1137 	tasks_system_suspend(newSuspend);
1138 	return true;
1139 }
1140 
1141 //******************************************************************************
1142 
1143 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1144 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1145 {
1146 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1147 	uint32_t    notifyRef  = (uint32_t)(uintptr_t) p1;
1148 	uint32_t    powerState = rootDomain->getPowerState();
1149 
1150 	DLOG("disk_sync_callout ps=%u\n", powerState);
1151 
1152 	if (ON_STATE == powerState) {
1153 		sync_internal();
1154 
1155 #if HIBERNATION
1156 		// Block sleep until trim issued on previous wake path is completed.
1157 		IOHibernateSystemPostWake(true);
1158 #endif
1159 	}
1160 #if HIBERNATION
1161 	else {
1162 		IOHibernateSystemPostWake(false);
1163 
1164 		rootDomain->sleepWakeDebugSaveSpinDumpFile();
1165 	}
1166 #endif
1167 
1168 	rootDomain->allowPowerChange(notifyRef);
1169 	DLOG("disk_sync_callout finish\n");
1170 }
1171 
1172 //******************************************************************************
1173 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1174 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1175 {
1176 	AbsoluteTime    endTime;
1177 	UInt64          nano = 0;
1178 
1179 	clock_get_uptime(&endTime);
1180 	if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1181 		*elapsedTime = 0;
1182 	} else {
1183 		SUB_ABSOLUTETIME(&endTime, startTime);
1184 		absolutetime_to_nanoseconds(endTime, &nano);
1185 		*elapsedTime = endTime;
1186 	}
1187 
1188 	return (UInt32)(nano / NSEC_PER_MSEC);
1189 }
1190 
1191 //******************************************************************************
1192 
1193 static int
1194 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1195 {
1196 	struct timeval *swt = (struct timeval *)arg1;
1197 	struct proc *p = req->p;
1198 
1199 	if (p == kernproc) {
1200 		return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1201 	} else if (proc_is64bit(p)) {
1202 		struct user64_timeval t = {};
1203 		t.tv_sec = swt->tv_sec;
1204 		t.tv_usec = swt->tv_usec;
1205 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1206 	} else {
1207 		struct user32_timeval t = {};
1208 		t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1209 		t.tv_usec = swt->tv_usec;
1210 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1211 	}
1212 }
1213 
1214 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1215     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1216     &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1217 
1218 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1219     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1220     &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1221 
1222 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1223 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1224 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1225 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1226 
1227 static int
1228 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1229 {
1230 	int new_value, changed, error;
1231 
1232 	if (!gWillShutdownSysctlRegistered) {
1233 		return ENOENT;
1234 	}
1235 
1236 	error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1237 	if (changed) {
1238 		if (!gWillShutdown && (new_value == 1)) {
1239 			IOPMRootDomainWillShutdown();
1240 		} else {
1241 			error = EINVAL;
1242 		}
1243 	}
1244 	return error;
1245 }
1246 
1247 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1248     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1249     NULL, 0, sysctl_willshutdown, "I", "");
1250 
1251 #if defined(XNU_TARGET_OS_OSX)
1252 
1253 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1254 sysctl_progressmeterenable
1255 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1256 {
1257 	int error;
1258 	int new_value, changed;
1259 
1260 	error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1261 
1262 	if (changed) {
1263 		vc_enable_progressmeter(new_value);
1264 	}
1265 
1266 	return error;
1267 }
1268 
1269 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1270 sysctl_progressmeter
1271 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1272 {
1273 	int error;
1274 	int new_value, changed;
1275 
1276 	error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1277 
1278 	if (changed) {
1279 		vc_set_progressmeter(new_value);
1280 	}
1281 
1282 	return error;
1283 }
1284 
1285 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1286     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1287     NULL, 0, sysctl_progressmeterenable, "I", "");
1288 
1289 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1290     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1291     NULL, 0, sysctl_progressmeter, "I", "");
1292 
1293 #endif /* defined(XNU_TARGET_OS_OSX) */
1294 
1295 
1296 
1297 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1298 sysctl_consoleoptions
1299 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1300 {
1301 	int error, changed;
1302 	uint32_t new_value;
1303 
1304 	error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1305 
1306 	if (changed) {
1307 		vc_user_options.options = new_value;
1308 	}
1309 
1310 	return error;
1311 }
1312 
1313 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1314     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1315     NULL, 0, sysctl_consoleoptions, "I", "");
1316 
1317 
1318 static int
1319 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1320 {
1321 	return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1322 }
1323 
1324 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1325     CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1326     NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1327 
1328 
1329 static int
1330 sysctl_wakereason SYSCTL_HANDLER_ARGS
1331 {
1332 	char wr[sizeof(gWakeReasonString)];
1333 
1334 	wr[0] = '\0';
1335 	if (gRootDomain && gWakeReasonSysctlRegistered) {
1336 		gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1337 	} else {
1338 		return ENOENT;
1339 	}
1340 
1341 	return sysctl_io_string(req, wr, 0, 0, NULL);
1342 }
1343 
1344 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1345     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1346     NULL, 0, sysctl_wakereason, "A", "wakereason");
1347 
1348 static int
1349 sysctl_bootreason SYSCTL_HANDLER_ARGS
1350 {
1351 	if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1352 		return ENOENT;
1353 	}
1354 
1355 	return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1356 }
1357 
1358 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1359     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1360     NULL, 0, sysctl_bootreason, "A", "");
1361 
1362 static int
1363 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1364 {
1365 	char sr[sizeof(gShutdownReasonString)];
1366 
1367 	sr[0] = '\0';
1368 	if (gRootDomain && gShutdownReasonSysctlRegistered) {
1369 		gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1370 	} else {
1371 		return ENOENT;
1372 	}
1373 
1374 	return sysctl_io_string(req, sr, 0, 0, NULL);
1375 }
1376 
1377 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1378     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1379     NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1380 
1381 static int
1382 sysctl_targettype SYSCTL_HANDLER_ARGS
1383 {
1384 	IOService * root;
1385 	OSSharedPtr<OSObject>  obj;
1386 	OSData *    data;
1387 	char        tt[32];
1388 
1389 	tt[0] = '\0';
1390 	root = IOService::getServiceRoot();
1391 	if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1392 		if ((data = OSDynamicCast(OSData, obj.get()))) {
1393 			strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1394 		}
1395 	}
1396 	return sysctl_io_string(req, tt, 0, 0, NULL);
1397 }
1398 
1399 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1400     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1401     NULL, 0, sysctl_targettype, "A", "targettype");
1402 
1403 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1404 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1405 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1406 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1407 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1408 #if DEVELOPMENT || DEBUG
1409 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1410 #if defined(XNU_TARGET_OS_OSX)
1411 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1412 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1413 #endif /* defined(XNU_TARGET_OS_OSX) */
1414 #endif /* DEVELOPMENT || DEBUG */
1415 
1416 //******************************************************************************
1417 // AOT
1418 
1419 static int
1420 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1421 {
1422 	if (NULL == gRootDomain) {
1423 		return ENOENT;
1424 	}
1425 	if (NULL == gRootDomain->_aotMetrics) {
1426 		IOPMAOTMetrics nullMetrics = {};
1427 		return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1428 	}
1429 	return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1430 }
1431 
1432 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1433     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1434     NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1435 
1436 
1437 static int
update_aotmode(uint32_t mode)1438 update_aotmode(uint32_t mode)
1439 {
1440 	int result;
1441 
1442 	if (!gIOPMWorkLoop) {
1443 		return ENOENT;
1444 	}
1445 	result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1446 		unsigned int oldCount;
1447 
1448 		if (mode && !gRootDomain->_aotMetrics) {
1449 		        gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1450 		}
1451 
1452 		oldCount = gRootDomain->idleSleepPreventersCount();
1453 		gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1454 		gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1455 		return 0;
1456 	});
1457 	return result;
1458 }
1459 
1460 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1461 sysctl_aotmodebits
1462 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1463 {
1464 	int error, changed;
1465 	uint32_t new_value;
1466 
1467 	if (NULL == gRootDomain) {
1468 		return ENOENT;
1469 	}
1470 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1471 	if (changed && gIOPMWorkLoop) {
1472 		error = update_aotmode(new_value);
1473 	}
1474 
1475 	return error;
1476 }
1477 
1478 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1479     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1480     NULL, 0, sysctl_aotmodebits, "I", "");
1481 
1482 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1483 sysctl_aotmode
1484 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1485 {
1486 	int error, changed;
1487 	uint32_t new_value;
1488 
1489 	if (NULL == gRootDomain) {
1490 		return ENOENT;
1491 	}
1492 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1493 	if (changed && gIOPMWorkLoop) {
1494 		if (new_value) {
1495 			new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1496 		}
1497 		error = update_aotmode(new_value);
1498 	}
1499 
1500 	return error;
1501 }
1502 
1503 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1504     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1505     NULL, 0, sysctl_aotmode, "I", "");
1506 
1507 //******************************************************************************
1508 
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1513 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1514 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1515 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1516 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1517 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1518 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1519 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1520 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1521 
1522 //******************************************************************************
1523 // start
1524 //
1525 //******************************************************************************
1526 
1527 #define kRootDomainSettingsCount           20
1528 #define kRootDomainNoPublishSettingsCount  4
1529 
1530 bool
start(IOService * nub)1531 IOPMrootDomain::start( IOService * nub )
1532 {
1533 	OSSharedPtr<OSIterator>      psIterator;
1534 	OSSharedPtr<OSDictionary>    tmpDict;
1535 
1536 	super::start(nub);
1537 
1538 	gRootDomain = this;
1539 	gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1540 	gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1541 	gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1542 	gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1543 	gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1544 	gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1545 	gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1546 	gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1547 	gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1548 	gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1549 	gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1550 	gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1551 
1552 	gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1553 	gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1554 	gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1555 	gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1556 	gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1557 
1558 	sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1559 	sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1560 	gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1561 
1562 	OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1563 	{
1564 		OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1565 		gIOPMSettingAutoWakeSecondsKey,
1566 		gIOPMSettingAutoPowerSecondsKey,
1567 		gIOPMSettingAutoWakeCalendarKey,
1568 		gIOPMSettingAutoPowerCalendarKey,
1569 		gIOPMSettingDebugWakeRelativeKey,
1570 		gIOPMSettingDebugPowerRelativeKey,
1571 		OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1572 		OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1573 		OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1574 		OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1575 		OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1576 		OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1577 		OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1578 		OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1579 		OSSymbol::withCString(kIOPMStateConsoleShutdown),
1580 		OSSymbol::withCString(kIOPMSettingProModeControl),
1581 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1582 		gIOPMSettingSilentRunningKey,
1583 		gIOPMSettingLowLatencyAudioModeKey,
1584 	};
1585 
1586 	OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1587 	{
1588 		OSSymbol::withCString(kIOPMSettingProModeControl),
1589 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1590 		gIOPMSettingSilentRunningKey,
1591 		gIOPMSettingLowLatencyAudioModeKey,
1592 	};
1593 
1594 #if DEVELOPMENT || DEBUG
1595 #if defined(XNU_TARGET_OS_OSX)
1596 	PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1597 	PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1598 #endif /* defined(XNU_TARGET_OS_OSX) */
1599 #endif /* DEVELOPMENT || DEBUG */
1600 
1601 	PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1602 	PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1603 	PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1604 	PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1605 	PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1606 	PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1607 
1608 	// read noidle setting from Device Tree
1609 	if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1610 		DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1611 	}
1612 
1613 	queue_init(&aggressivesQueue);
1614 	aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1615 	aggressivesData = OSData::withCapacity(
1616 		sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1617 
1618 	featuresDictLock = IOLockAlloc();
1619 	settingsCtrlLock = IOLockAlloc();
1620 	wakeEventLock = IOLockAlloc();
1621 	gHaltLogLock = IOLockAlloc();
1622 	setPMRootDomain(this);
1623 
1624 	extraSleepTimer = thread_call_allocate(
1625 		idleSleepTimerExpired,
1626 		(thread_call_param_t) this);
1627 
1628 	powerButtonDown = thread_call_allocate(
1629 		powerButtonDownCallout,
1630 		(thread_call_param_t) this);
1631 
1632 	powerButtonUp = thread_call_allocate(
1633 		powerButtonUpCallout,
1634 		(thread_call_param_t) this);
1635 
1636 	diskSyncCalloutEntry = thread_call_allocate(
1637 		&disk_sync_callout,
1638 		(thread_call_param_t) this);
1639 	updateConsoleUsersEntry = thread_call_allocate(
1640 		&updateConsoleUsersCallout,
1641 		(thread_call_param_t) this);
1642 
1643 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1644 	fullWakeThreadCall = thread_call_allocate_with_options(
1645 		OSMemberFunctionCast(thread_call_func_t, this,
1646 		&IOPMrootDomain::fullWakeDelayedWork),
1647 		(thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1648 		THREAD_CALL_OPTIONS_ONCE);
1649 #endif
1650 
1651 	setProperty(kIOSleepSupportedKey, true);
1652 
1653 	bzero(&gPMStats, sizeof(gPMStats));
1654 
1655 	pmTracer = PMTraceWorker::tracer(this);
1656 
1657 	pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1658 
1659 	userDisabledAllSleep = false;
1660 	systemBooting = true;
1661 	idleSleepEnabled = false;
1662 	idleSleepRevertible = true;
1663 	sleepSlider = 0;
1664 	idleSleepTimerPending = false;
1665 	wrangler = NULL;
1666 	clamshellClosed = false;
1667 	clamshellExists = false;
1668 #if DISPLAY_WRANGLER_PRESENT
1669 	clamshellDisabled = true;
1670 #else
1671 	clamshellDisabled = false;
1672 #endif
1673 	clamshellIgnoreClose = false;
1674 	acAdaptorConnected = true;
1675 	clamshellSleepDisableMask = 0;
1676 	gWakeReasonString[0] = '\0';
1677 
1678 	// Initialize to user active.
1679 	// Will never transition to user inactive w/o wrangler.
1680 	fullWakeReason = kFullWakeReasonLocalUser;
1681 	userIsActive = userWasActive = true;
1682 	clock_get_uptime(&gUserActiveAbsTime);
1683 	setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1684 
1685 	// Set the default system capabilities at boot.
1686 	_currentCapability = kIOPMSystemCapabilityCPU      |
1687 	    kIOPMSystemCapabilityGraphics |
1688 	    kIOPMSystemCapabilityAudio    |
1689 	    kIOPMSystemCapabilityNetwork;
1690 
1691 	_pendingCapability = _currentCapability;
1692 	_desiredCapability = _currentCapability;
1693 	_highestCapability = _currentCapability;
1694 	setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1695 
1696 	queuedSleepWakeUUIDString = NULL;
1697 	initializeBootSessionUUID();
1698 	pmStatsAppResponses     = OSArray::withCapacity(5);
1699 	_statsNameKey           = OSSymbol::withCString(kIOPMStatsNameKey);
1700 	_statsPIDKey            = OSSymbol::withCString(kIOPMStatsPIDKey);
1701 	_statsTimeMSKey         = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1702 	_statsResponseTypeKey   = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1703 	_statsMessageTypeKey    = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1704 	_statsPowerCapsKey      = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1705 	assertOnWakeSecs        = -1;// Invalid value to prevent updates
1706 
1707 	pmStatsLock = IOLockAlloc();
1708 	idxPMCPUClamshell = kCPUUnknownIndex;
1709 	idxPMCPULimitedPower = kCPUUnknownIndex;
1710 
1711 	tmpDict = OSDictionary::withCapacity(1);
1712 	setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1713 
1714 	// Set a default "SystemPowerProfileOverrideDict" for platform
1715 	// drivers without any overrides.
1716 	if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1717 		tmpDict = OSDictionary::withCapacity(1);
1718 		setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1719 	}
1720 
1721 	settingsCallbacks = OSDictionary::withCapacity(1);
1722 
1723 	// Create a list of the valid PM settings that we'll relay to
1724 	// interested clients in setProperties() => setPMSetting()
1725 	allowedPMSettings = OSArray::withObjects(
1726 		(const OSObject **)settingsArr,
1727 		kRootDomainSettingsCount,
1728 		0);
1729 
1730 	// List of PM settings that should not automatically publish itself
1731 	// as a feature when registered by a listener.
1732 	noPublishPMSettings = OSArray::withObjects(
1733 		(const OSObject **)noPublishSettingsArr,
1734 		kRootDomainNoPublishSettingsCount,
1735 		0);
1736 
1737 	fPMSettingsDict = OSDictionary::withCapacity(5);
1738 	preventIdleSleepList = OSSet::withCapacity(8);
1739 	preventSystemSleepList = OSSet::withCapacity(2);
1740 
1741 	PMinit(); // creates gIOPMWorkLoop
1742 	gIOPMWorkLoop = getIOPMWorkloop();
1743 
1744 	// Create IOPMPowerStateQueue used to queue external power
1745 	// events, and to handle those events on the PM work loop.
1746 	pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1747 		this, OSMemberFunctionCast(IOEventSource::Action, this,
1748 		&IOPMrootDomain::dispatchPowerEvent));
1749 	gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1750 
1751 	_aotMode = 0;
1752 	_aotTimerES = IOTimerEventSource::timerEventSource(this,
1753 	    OSMemberFunctionCast(IOTimerEventSource::Action,
1754 	    this, &IOPMrootDomain::aotEvaluate));
1755 	gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1756 
1757 	// Avoid publishing service early so gIOPMWorkLoop is
1758 	// guaranteed to be initialized by rootDomain.
1759 	publishPMRootDomain();
1760 
1761 	// create our power parent
1762 	gPatriarch = new IORootParent;
1763 	gPatriarch->init();
1764 	gPatriarch->attach(this);
1765 	gPatriarch->start(this);
1766 	gPatriarch->addPowerChild(this);
1767 
1768 	registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1769 	changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1770 
1771 	// install power change handler
1772 	gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1773 
1774 #if DISPLAY_WRANGLER_PRESENT
1775 	wranglerIdleSettings = OSDictionary::withCapacity(1);
1776 	OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1777 
1778 	if (wranglerIdleSettings && wranglerIdlePeriod) {
1779 		wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1780 		    wranglerIdlePeriod.get());
1781 	}
1782 
1783 #endif /* DISPLAY_WRANGLER_PRESENT */
1784 
1785 	lowLatencyAudioNotifierDict       = OSDictionary::withCapacity(2);
1786 	lowLatencyAudioNotifyStateSym     = OSSymbol::withCString("LowLatencyAudioNotifyState");
1787 	lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1788 	lowLatencyAudioNotifyStateVal     = OSNumber::withNumber(0ull, 32);
1789 	lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1790 
1791 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1792 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1793 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1794 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1795 	}
1796 
1797 	OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1798 	setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1799 
1800 	// IOBacklightDisplay can take a long time to load at boot, or it may
1801 	// not load at all if you're booting with clamshell closed. We publish
1802 	// 'DisplayDims' here redundantly to get it published early and at all.
1803 	OSSharedPtr<OSDictionary> matching;
1804 	matching = serviceMatching("IOPMPowerSource");
1805 	psIterator = getMatchingServices(matching.get());
1806 
1807 	if (psIterator && psIterator->getNextObject()) {
1808 		// There's at least one battery on the system, so we publish
1809 		// 'DisplayDims' support for the LCD.
1810 		publishFeature("DisplayDims");
1811 	}
1812 
1813 	// read swd_panic boot-arg
1814 	PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1815 	gWillShutdownSysctlRegistered = true;
1816 
1817 #if HIBERNATION
1818 	IOHibernateSystemInit(this);
1819 #endif
1820 
1821 	registerService();                  // let clients find us
1822 
1823 	return true;
1824 }
1825 
1826 //******************************************************************************
1827 // setProperties
1828 //
1829 // Receive a setProperty call
1830 // The "System Boot" property means the system is completely booted.
1831 //******************************************************************************
1832 
1833 IOReturn
setProperties(OSObject * props_obj)1834 IOPMrootDomain::setProperties( OSObject * props_obj )
1835 {
1836 	IOReturn        return_value = kIOReturnSuccess;
1837 	OSDictionary    *dict = OSDynamicCast(OSDictionary, props_obj);
1838 	OSBoolean       *b = NULL;
1839 	OSNumber        *n = NULL;
1840 	const OSSymbol  *key = NULL;
1841 	OSObject        *obj = NULL;
1842 	OSSharedPtr<OSCollectionIterator> iter;
1843 
1844 	if (!dict) {
1845 		return kIOReturnBadArgument;
1846 	}
1847 
1848 	bool clientEntitled = false;
1849 	{
1850 		OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1851 		clientEntitled = (obj == kOSBooleanTrue);
1852 	}
1853 
1854 	if (!clientEntitled) {
1855 		const char * errorSuffix = NULL;
1856 
1857 		// IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1858 		// That API can set 6 possible keys that are checked below.
1859 		if ((dict->getCount() == 1) &&
1860 		    (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1861 		    dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1862 		    dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1863 		    dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1864 		    dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1865 		    dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1866 			return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1867 			if (return_value != kIOReturnSuccess) {
1868 				errorSuffix = "privileged";
1869 			}
1870 		} else {
1871 			return_value = kIOReturnNotPermitted;
1872 			errorSuffix = "entitled";
1873 		}
1874 
1875 		if (return_value != kIOReturnSuccess) {
1876 			OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1877 			DLOG("%s failed, process %s is not %s\n", __func__,
1878 			    procName ? procName->getCStringNoCopy() : "", errorSuffix);
1879 			return return_value;
1880 		}
1881 	}
1882 
1883 	OSSharedPtr<const OSSymbol> publish_simulated_battery_string    = OSSymbol::withCString("SoftwareSimulatedBatteries");
1884 	OSSharedPtr<const OSSymbol> boot_complete_string                = OSSymbol::withCString("System Boot Complete");
1885 	OSSharedPtr<const OSSymbol> sys_shutdown_string                 = OSSymbol::withCString("System Shutdown");
1886 	OSSharedPtr<const OSSymbol> stall_halt_string                   = OSSymbol::withCString("StallSystemAtHalt");
1887 	OSSharedPtr<const OSSymbol> battery_warning_disabled_string     = OSSymbol::withCString("BatteryWarningsDisabled");
1888 	OSSharedPtr<const OSSymbol> idle_seconds_string                 = OSSymbol::withCString("System Idle Seconds");
1889 	OSSharedPtr<const OSSymbol> idle_milliseconds_string            = OSSymbol::withCString("System Idle Milliseconds");
1890 	OSSharedPtr<const OSSymbol> sleepdisabled_string                = OSSymbol::withCString("SleepDisabled");
1891 	OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string        = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1892 	OSSharedPtr<const OSSymbol> loginwindow_progress_string         = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1893 	OSSharedPtr<const OSSymbol> coredisplay_progress_string         = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1894 	OSSharedPtr<const OSSymbol> coregraphics_progress_string        = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1895 #if DEBUG || DEVELOPMENT
1896 	OSSharedPtr<const OSSymbol> clamshell_close_string              = OSSymbol::withCString("IOPMTestClamshellClose");
1897 	OSSharedPtr<const OSSymbol> clamshell_open_string               = OSSymbol::withCString("IOPMTestClamshellOpen");
1898 	OSSharedPtr<const OSSymbol> ac_detach_string                    = OSSymbol::withCString("IOPMTestACDetach");
1899 	OSSharedPtr<const OSSymbol> ac_attach_string                    = OSSymbol::withCString("IOPMTestACAttach");
1900 	OSSharedPtr<const OSSymbol> desktopmode_set_string              = OSSymbol::withCString("IOPMTestDesktopModeSet");
1901 	OSSharedPtr<const OSSymbol> desktopmode_remove_string           = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1902 #endif
1903 
1904 #if HIBERNATION
1905 	OSSharedPtr<const OSSymbol> hibernatemode_string                = OSSymbol::withCString(kIOHibernateModeKey);
1906 	OSSharedPtr<const OSSymbol> hibernatefile_string                = OSSymbol::withCString(kIOHibernateFileKey);
1907 	OSSharedPtr<const OSSymbol> hibernatefilemin_string             = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1908 	OSSharedPtr<const OSSymbol> hibernatefilemax_string             = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1909 	OSSharedPtr<const OSSymbol> hibernatefreeratio_string           = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1910 	OSSharedPtr<const OSSymbol> hibernatefreetime_string            = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1911 #endif
1912 
1913 	iter = OSCollectionIterator::withCollection(dict);
1914 	if (!iter) {
1915 		return_value = kIOReturnNoMemory;
1916 		goto exit;
1917 	}
1918 
1919 	while ((key = (const OSSymbol *) iter->getNextObject()) &&
1920 	    (obj = dict->getObject(key))) {
1921 		if (key->isEqualTo(publish_simulated_battery_string.get())) {
1922 			if (OSDynamicCast(OSBoolean, obj)) {
1923 				publishResource(key, kOSBooleanTrue);
1924 			}
1925 		} else if (key->isEqualTo(idle_seconds_string.get())) {
1926 			if ((n = OSDynamicCast(OSNumber, obj))) {
1927 				setProperty(key, n);
1928 				idleMilliSeconds = n->unsigned32BitValue() * 1000;
1929 			}
1930 		} else if (key->isEqualTo(idle_milliseconds_string.get())) {
1931 			if ((n = OSDynamicCast(OSNumber, obj))) {
1932 				setProperty(key, n);
1933 				idleMilliSeconds = n->unsigned32BitValue();
1934 			}
1935 		} else if (key->isEqualTo(boot_complete_string.get())) {
1936 			pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1937 		} else if (key->isEqualTo(sys_shutdown_string.get())) {
1938 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1939 				pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1940 			}
1941 		} else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1942 			setProperty(key, obj);
1943 		}
1944 #if HIBERNATION
1945 		else if (key->isEqualTo(hibernatemode_string.get()) ||
1946 		    key->isEqualTo(hibernatefilemin_string.get()) ||
1947 		    key->isEqualTo(hibernatefilemax_string.get()) ||
1948 		    key->isEqualTo(hibernatefreeratio_string.get()) ||
1949 		    key->isEqualTo(hibernatefreetime_string.get())) {
1950 			if ((n = OSDynamicCast(OSNumber, obj))) {
1951 				setProperty(key, n);
1952 			}
1953 		} else if (key->isEqualTo(hibernatefile_string.get())) {
1954 			OSString * str = OSDynamicCast(OSString, obj);
1955 			if (str) {
1956 				setProperty(key, str);
1957 			}
1958 		}
1959 #endif
1960 		else if (key->isEqualTo(sleepdisabled_string.get())) {
1961 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1962 				setProperty(key, b);
1963 				pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1964 			}
1965 		} else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1966 			obj->retain();
1967 			pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1968 		} else if (key->isEqualTo(loginwindow_progress_string.get())) {
1969 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1970 				uint32_t data = n->unsigned32BitValue();
1971 				pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1972 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1973 			}
1974 		} else if (key->isEqualTo(coredisplay_progress_string.get())) {
1975 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1976 				uint32_t data = n->unsigned32BitValue();
1977 				pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1978 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1979 			}
1980 		} else if (key->isEqualTo(coregraphics_progress_string.get())) {
1981 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1982 				uint32_t data = n->unsigned32BitValue();
1983 				pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1984 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1985 			}
1986 		} else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1987 		    key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1988 		    key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1989 		    key->isEqualTo(stall_halt_string.get())) {
1990 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1991 				setProperty(key, b);
1992 			}
1993 		} else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1994 		    key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1995 		    key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1996 		    key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1997 			if ((n = OSDynamicCast(OSNumber, obj))) {
1998 				setProperty(key, n);
1999 			}
2000 		} else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
2001 			if (kOSBooleanTrue == obj) {
2002 				OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2003 			} else {
2004 				OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2005 			}
2006 			DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2007 		}
2008 #if DEBUG || DEVELOPMENT
2009 		else if (key->isEqualTo(clamshell_close_string.get())) {
2010 			DLOG("SetProperties: setting clamshell close\n");
2011 			UInt32 msg = kIOPMClamshellClosed;
2012 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2013 		} else if (key->isEqualTo(clamshell_open_string.get())) {
2014 			DLOG("SetProperties: setting clamshell open\n");
2015 			UInt32 msg = kIOPMClamshellOpened;
2016 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2017 		} else if (key->isEqualTo(ac_detach_string.get())) {
2018 			DLOG("SetProperties: setting ac detach\n");
2019 			UInt32 msg = kIOPMSetACAdaptorConnected;
2020 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2021 		} else if (key->isEqualTo(ac_attach_string.get())) {
2022 			DLOG("SetProperties: setting ac attach\n");
2023 			UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2024 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2025 		} else if (key->isEqualTo(desktopmode_set_string.get())) {
2026 			DLOG("SetProperties: setting desktopmode");
2027 			UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2028 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2029 		} else if (key->isEqualTo(desktopmode_remove_string.get())) {
2030 			DLOG("SetProperties: removing desktopmode\n");
2031 			UInt32 msg = kIOPMSetDesktopMode;
2032 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2033 		}
2034 #endif
2035 		// Relay our allowed PM settings onto our registered PM clients
2036 		else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2037 			return_value = setPMSetting(key, obj);
2038 			if (kIOReturnSuccess != return_value) {
2039 				break;
2040 			}
2041 		} else {
2042 			DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2043 		}
2044 	}
2045 
2046 exit:
2047 	return return_value;
2048 }
2049 
2050 // MARK: -
2051 // MARK: Aggressiveness
2052 
2053 //******************************************************************************
2054 // setAggressiveness
2055 //
2056 // Override IOService::setAggressiveness()
2057 //******************************************************************************
2058 
2059 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2060 IOPMrootDomain::setAggressiveness(
2061 	unsigned long   type,
2062 	unsigned long   value )
2063 {
2064 	return setAggressiveness( type, value, 0 );
2065 }
2066 
2067 /*
2068  * Private setAggressiveness() with an internal options argument.
2069  */
2070 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2071 IOPMrootDomain::setAggressiveness(
2072 	unsigned long   type,
2073 	unsigned long   value,
2074 	IOOptionBits    options )
2075 {
2076 	AggressivesRequest *    entry;
2077 	AggressivesRequest *    request;
2078 	bool                    found = false;
2079 
2080 	if ((type > UINT_MAX) || (value > UINT_MAX)) {
2081 		return kIOReturnBadArgument;
2082 	}
2083 
2084 	if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2085 		DLOG("setAggressiveness(%x) %s = %u\n",
2086 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2087 	} else {
2088 		DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2089 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2090 	}
2091 
2092 	request = IOMallocType(AggressivesRequest);
2093 	request->options  = options;
2094 	request->dataType = kAggressivesRequestTypeRecord;
2095 	request->data.record.type  = (uint32_t) type;
2096 	request->data.record.value = (uint32_t) value;
2097 
2098 	AGGRESSIVES_LOCK();
2099 
2100 	// Update disk quick spindown flag used by getAggressiveness().
2101 	// Never merge requests with quick spindown flags set.
2102 
2103 	if (options & kAggressivesOptionQuickSpindownEnable) {
2104 		gAggressivesState |= kAggressivesStateQuickSpindown;
2105 	} else if (options & kAggressivesOptionQuickSpindownDisable) {
2106 		gAggressivesState &= ~kAggressivesStateQuickSpindown;
2107 	} else {
2108 		// Coalesce requests with identical aggressives types.
2109 		// Deal with callers that calls us too "aggressively".
2110 
2111 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2112 		{
2113 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2114 			    (entry->data.record.type == type) &&
2115 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2116 				entry->data.record.value = (uint32_t) value;
2117 				found = true;
2118 				break;
2119 			}
2120 		}
2121 	}
2122 
2123 	if (!found) {
2124 		queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2125 	}
2126 
2127 	AGGRESSIVES_UNLOCK();
2128 
2129 	if (found) {
2130 		IOFreeType(request, AggressivesRequest);
2131 	}
2132 
2133 	if (options & kAggressivesOptionSynchronous) {
2134 		handleAggressivesRequests(); // not truly synchronous
2135 	} else {
2136 		thread_call_enter(aggressivesThreadCall);
2137 	}
2138 
2139 	return kIOReturnSuccess;
2140 }
2141 
2142 //******************************************************************************
2143 // getAggressiveness
2144 //
2145 // Override IOService::setAggressiveness()
2146 // Fetch the aggressiveness factor with the given type.
2147 //******************************************************************************
2148 
2149 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2150 IOPMrootDomain::getAggressiveness(
2151 	unsigned long   type,
2152 	unsigned long * outLevel )
2153 {
2154 	uint32_t    value  = 0;
2155 	int         source = 0;
2156 
2157 	if (!outLevel || (type > UINT_MAX)) {
2158 		return kIOReturnBadArgument;
2159 	}
2160 
2161 	AGGRESSIVES_LOCK();
2162 
2163 	// Disk quick spindown in effect, report value = 1
2164 
2165 	if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2166 	    (type == kPMMinutesToSpinDown)) {
2167 		value  = kAggressivesMinValue;
2168 		source = 1;
2169 	}
2170 
2171 	// Consult the pending request queue.
2172 
2173 	if (!source) {
2174 		AggressivesRequest * entry;
2175 
2176 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2177 		{
2178 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2179 			    (entry->data.record.type == type) &&
2180 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2181 				value  = entry->data.record.value;
2182 				source = 2;
2183 				break;
2184 			}
2185 		}
2186 	}
2187 
2188 	// Consult the backend records.
2189 
2190 	if (!source && aggressivesData) {
2191 		AggressivesRecord * record;
2192 		int                 i, count;
2193 
2194 		count  = aggressivesData->getLength() / sizeof(AggressivesRecord);
2195 		record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2196 
2197 		for (i = 0; i < count; i++, record++) {
2198 			if (record->type == type) {
2199 				value  = record->value;
2200 				source = 3;
2201 				break;
2202 			}
2203 		}
2204 	}
2205 
2206 	AGGRESSIVES_UNLOCK();
2207 
2208 	if (source) {
2209 		*outLevel = (unsigned long) value;
2210 		return kIOReturnSuccess;
2211 	} else {
2212 		DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2213 		*outLevel = 0; // default return = 0, driver may not check for error
2214 		return kIOReturnInvalid;
2215 	}
2216 }
2217 
2218 //******************************************************************************
2219 // joinAggressiveness
2220 //
2221 // Request from IOService to join future aggressiveness broadcasts.
2222 //******************************************************************************
2223 
2224 IOReturn
joinAggressiveness(IOService * service)2225 IOPMrootDomain::joinAggressiveness(
2226 	IOService * service )
2227 {
2228 	AggressivesRequest *    request;
2229 
2230 	if (!service || (service == this)) {
2231 		return kIOReturnBadArgument;
2232 	}
2233 
2234 	DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2235 
2236 	request = IOMallocType(AggressivesRequest);
2237 	request->dataType = kAggressivesRequestTypeService;
2238 	request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2239 
2240 	AGGRESSIVES_LOCK();
2241 	queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2242 	AGGRESSIVES_UNLOCK();
2243 
2244 	thread_call_enter(aggressivesThreadCall);
2245 
2246 	return kIOReturnSuccess;
2247 }
2248 
2249 //******************************************************************************
2250 // handleAggressivesRequests
2251 //
2252 // Backend thread processes all incoming aggressiveness requests in the queue.
2253 //******************************************************************************
2254 
2255 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2256 handleAggressivesFunction(
2257 	thread_call_param_t param1,
2258 	thread_call_param_t param2 )
2259 {
2260 	if (param1) {
2261 		((IOPMrootDomain *) param1)->handleAggressivesRequests();
2262 	}
2263 }
2264 
2265 void
handleAggressivesRequests(void)2266 IOPMrootDomain::handleAggressivesRequests( void )
2267 {
2268 	AggressivesRecord *     start;
2269 	AggressivesRecord *     record;
2270 	AggressivesRequest *    request;
2271 	queue_head_t            joinedQueue;
2272 	int                     i, count;
2273 	bool                    broadcast;
2274 	bool                    found;
2275 	bool                    pingSelf = false;
2276 
2277 	AGGRESSIVES_LOCK();
2278 
2279 	if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2280 	    queue_empty(&aggressivesQueue)) {
2281 		goto unlock_done;
2282 	}
2283 
2284 	gAggressivesState |= kAggressivesStateBusy;
2285 	count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2286 	start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2287 
2288 	do{
2289 		broadcast = false;
2290 		queue_init(&joinedQueue);
2291 
2292 		do{
2293 			// Remove request from the incoming queue in FIFO order.
2294 			queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2295 			switch (request->dataType) {
2296 			case kAggressivesRequestTypeRecord:
2297 				// Update existing record if found.
2298 				found = false;
2299 				for (i = 0, record = start; i < count; i++, record++) {
2300 					if (record->type == request->data.record.type) {
2301 						found = true;
2302 
2303 						if (request->options & kAggressivesOptionQuickSpindownEnable) {
2304 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2305 								broadcast = true;
2306 								record->flags |= (kAggressivesRecordFlagMinValue |
2307 								    kAggressivesRecordFlagModified);
2308 								DLOG("disk spindown accelerated, was %u min\n",
2309 								    record->value);
2310 							}
2311 						} else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2312 							if (record->flags & kAggressivesRecordFlagMinValue) {
2313 								broadcast = true;
2314 								record->flags |= kAggressivesRecordFlagModified;
2315 								record->flags &= ~kAggressivesRecordFlagMinValue;
2316 								DLOG("disk spindown restored to %u min\n",
2317 								    record->value);
2318 							}
2319 						} else if (record->value != request->data.record.value) {
2320 							record->value = request->data.record.value;
2321 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2322 								broadcast = true;
2323 								record->flags |= kAggressivesRecordFlagModified;
2324 							}
2325 						}
2326 						break;
2327 					}
2328 				}
2329 
2330 				// No matching record, append a new record.
2331 				if (!found &&
2332 				    ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2333 					AggressivesRecord   newRecord;
2334 
2335 					newRecord.flags = kAggressivesRecordFlagModified;
2336 					newRecord.type  = request->data.record.type;
2337 					newRecord.value = request->data.record.value;
2338 					if (request->options & kAggressivesOptionQuickSpindownEnable) {
2339 						newRecord.flags |= kAggressivesRecordFlagMinValue;
2340 						DLOG("disk spindown accelerated\n");
2341 					}
2342 
2343 					aggressivesData->appendValue(newRecord);
2344 
2345 					// OSData may have switched to another (larger) buffer.
2346 					count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2347 					start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2348 					broadcast = true;
2349 				}
2350 
2351 				// Finished processing the request, release it.
2352 				IOFreeType(request, AggressivesRequest);
2353 				break;
2354 
2355 			case kAggressivesRequestTypeService:
2356 				// synchronizeAggressives() will free request.
2357 				queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2358 				break;
2359 
2360 			default:
2361 				panic("bad aggressives request type %x", request->dataType);
2362 				break;
2363 			}
2364 		} while (!queue_empty(&aggressivesQueue));
2365 
2366 		// Release the lock to perform work, with busy flag set.
2367 		if (!queue_empty(&joinedQueue) || broadcast) {
2368 			AGGRESSIVES_UNLOCK();
2369 			if (!queue_empty(&joinedQueue)) {
2370 				synchronizeAggressives(&joinedQueue, start, count);
2371 			}
2372 			if (broadcast) {
2373 				broadcastAggressives(start, count);
2374 			}
2375 			AGGRESSIVES_LOCK();
2376 		}
2377 
2378 		// Remove the modified flag from all records.
2379 		for (i = 0, record = start; i < count; i++, record++) {
2380 			if ((record->flags & kAggressivesRecordFlagModified) &&
2381 			    ((record->type == kPMMinutesToDim) ||
2382 			    (record->type == kPMMinutesToSleep))) {
2383 				pingSelf = true;
2384 			}
2385 
2386 			record->flags &= ~kAggressivesRecordFlagModified;
2387 		}
2388 
2389 		// Check the incoming queue again since new entries may have been
2390 		// added while lock was released above.
2391 	} while (!queue_empty(&aggressivesQueue));
2392 
2393 	gAggressivesState &= ~kAggressivesStateBusy;
2394 
2395 unlock_done:
2396 	AGGRESSIVES_UNLOCK();
2397 
2398 	// Root domain is interested in system and display sleep slider changes.
2399 	// Submit a power event to handle those changes on the PM work loop.
2400 
2401 	if (pingSelf && pmPowerStateQueue) {
2402 		pmPowerStateQueue->submitPowerEvent(
2403 			kPowerEventPolicyStimulus,
2404 			(void *) kStimulusAggressivenessChanged );
2405 	}
2406 }
2407 
2408 //******************************************************************************
2409 // synchronizeAggressives
2410 //
2411 // Push all known aggressiveness records to one or more IOService.
2412 //******************************************************************************
2413 
2414 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2415 IOPMrootDomain::synchronizeAggressives(
2416 	queue_head_t *              joinedQueue,
2417 	const AggressivesRecord *   array,
2418 	int                         count )
2419 {
2420 	OSSharedPtr<IOService>      service;
2421 	AggressivesRequest *        request;
2422 	const AggressivesRecord *   record;
2423 	IOPMDriverCallEntry         callEntry;
2424 	uint32_t                    value;
2425 	int                         i;
2426 
2427 	while (!queue_empty(joinedQueue)) {
2428 		queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2429 		if (request->dataType == kAggressivesRequestTypeService) {
2430 			// retained by joinAggressiveness(), so take ownership
2431 			service = os::move(request->data.service);
2432 		} else {
2433 			service.reset();
2434 		}
2435 
2436 		IOFreeType(request, AggressivesRequest);
2437 		request = NULL;
2438 
2439 		if (service) {
2440 			if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2441 				for (i = 0, record = array; i < count; i++, record++) {
2442 					value = record->value;
2443 					if (record->flags & kAggressivesRecordFlagMinValue) {
2444 						value = kAggressivesMinValue;
2445 					}
2446 
2447 					_LOG("synchronizeAggressives 0x%x = %u to %s\n",
2448 					    record->type, value, service->getName());
2449 					service->setAggressiveness(record->type, value);
2450 				}
2451 				service->deassertPMDriverCall(&callEntry);
2452 			}
2453 		}
2454 	}
2455 }
2456 
2457 //******************************************************************************
2458 // broadcastAggressives
2459 //
2460 // Traverse PM tree and call setAggressiveness() for records that have changed.
2461 //******************************************************************************
2462 
2463 void
broadcastAggressives(const AggressivesRecord * array,int count)2464 IOPMrootDomain::broadcastAggressives(
2465 	const AggressivesRecord *   array,
2466 	int                         count )
2467 {
2468 	OSSharedPtr<IORegistryIterator> iter;
2469 	IORegistryEntry                *entry;
2470 	OSSharedPtr<IORegistryEntry>    child;
2471 	IOPowerConnection              *connect;
2472 	IOService                      *service;
2473 	const AggressivesRecord        *record;
2474 	IOPMDriverCallEntry             callEntry;
2475 	uint32_t                        value;
2476 	int                             i;
2477 
2478 	iter = IORegistryIterator::iterateOver(
2479 		this, gIOPowerPlane, kIORegistryIterateRecursively);
2480 	if (iter) {
2481 		do{
2482 			// !! reset the iterator
2483 			iter->reset();
2484 			while ((entry = iter->getNextObject())) {
2485 				connect = OSDynamicCast(IOPowerConnection, entry);
2486 				if (!connect || !connect->getReadyFlag()) {
2487 					continue;
2488 				}
2489 
2490 				child = connect->copyChildEntry(gIOPowerPlane);
2491 				if (child) {
2492 					if ((service = OSDynamicCast(IOService, child.get()))) {
2493 						if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2494 							for (i = 0, record = array; i < count; i++, record++) {
2495 								if (record->flags & kAggressivesRecordFlagModified) {
2496 									value = record->value;
2497 									if (record->flags & kAggressivesRecordFlagMinValue) {
2498 										value = kAggressivesMinValue;
2499 									}
2500 									_LOG("broadcastAggressives %x = %u to %s\n",
2501 									    record->type, value, service->getName());
2502 									service->setAggressiveness(record->type, value);
2503 								}
2504 							}
2505 							service->deassertPMDriverCall(&callEntry);
2506 						}
2507 					}
2508 				}
2509 			}
2510 		}while (!entry && !iter->isValid());
2511 	}
2512 }
2513 
2514 //*****************************************
2515 // stackshot on power button press
2516 // ***************************************
2517 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2518 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2519 {
2520 	/* Power button pressed during wake
2521 	 * Take a stackshot
2522 	 */
2523 	DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2524 	((IOPMrootDomain *)us)->takeStackshot(false);
2525 }
2526 
2527 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2528 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2529 {
2530 	/* Power button released.
2531 	 * Delete any stackshot data
2532 	 */
2533 	DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2534 	((IOPMrootDomain *)us)->deleteStackshot();
2535 }
2536 //*************************************************************************
2537 //
2538 
2539 // MARK: -
2540 // MARK: System Sleep
2541 
2542 //******************************************************************************
2543 // startIdleSleepTimer
2544 //
2545 //******************************************************************************
2546 
2547 void
startIdleSleepTimer(uint32_t inMilliSeconds)2548 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2549 {
2550 	AbsoluteTime deadline;
2551 
2552 	ASSERT_GATED();
2553 	if (gNoIdleFlag) {
2554 		DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2555 		return;
2556 	}
2557 	if (inMilliSeconds) {
2558 		if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2559 			AbsoluteTime    now;
2560 			uint64_t        nsec_since_wake;
2561 			uint64_t                msec_since_wake;
2562 
2563 			// Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2564 			// after the most recent AP wake.
2565 			clock_get_uptime(&now);
2566 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2567 			absolutetime_to_nanoseconds(now, &nsec_since_wake);
2568 			msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2569 
2570 			if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2571 				uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2572 
2573 				// Ensure that our new idle timer is not less than inMilliSeconds,
2574 				// as we should only be increasing the timer duration, not decreasing it
2575 				if (newIdleTimer > inMilliSeconds) {
2576 					DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2577 					inMilliSeconds = newIdleTimer;
2578 				}
2579 			}
2580 		}
2581 		clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2582 		thread_call_enter_delayed(extraSleepTimer, deadline);
2583 		idleSleepTimerPending = true;
2584 	} else {
2585 		thread_call_enter(extraSleepTimer);
2586 	}
2587 	DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2588 }
2589 
2590 //******************************************************************************
2591 // cancelIdleSleepTimer
2592 //
2593 //******************************************************************************
2594 
2595 void
cancelIdleSleepTimer(void)2596 IOPMrootDomain::cancelIdleSleepTimer( void )
2597 {
2598 	ASSERT_GATED();
2599 	if (idleSleepTimerPending) {
2600 		DLOG("idle timer cancelled\n");
2601 		thread_call_cancel(extraSleepTimer);
2602 		idleSleepTimerPending = false;
2603 
2604 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2605 			AbsoluteTime    now;
2606 			clock_usec_t    microsecs;
2607 			clock_get_uptime(&now);
2608 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2609 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2610 			if (assertOnWakeReport) {
2611 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2612 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2613 			}
2614 		}
2615 	}
2616 }
2617 
2618 //******************************************************************************
2619 // idleSleepTimerExpired
2620 //
2621 //******************************************************************************
2622 
2623 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2624 idleSleepTimerExpired(
2625 	thread_call_param_t us, thread_call_param_t )
2626 {
2627 	((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2628 }
2629 
2630 //******************************************************************************
2631 // handleSleepTimerExpiration
2632 //
2633 // The time between the sleep idle timeout and the next longest one has elapsed.
2634 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2635 //******************************************************************************
2636 
2637 void
handleSleepTimerExpiration(void)2638 IOPMrootDomain::handleSleepTimerExpiration( void )
2639 {
2640 	if (!gIOPMWorkLoop->inGate()) {
2641 		gIOPMWorkLoop->runAction(
2642 			OSMemberFunctionCast(IOWorkLoop::Action, this,
2643 			&IOPMrootDomain::handleSleepTimerExpiration),
2644 			this);
2645 		return;
2646 	}
2647 
2648 	DLOG("sleep timer expired\n");
2649 	ASSERT_GATED();
2650 
2651 	idleSleepTimerPending = false;
2652 	setQuickSpinDownTimeout();
2653 	adjustPowerState(true);
2654 }
2655 
2656 //******************************************************************************
2657 // getTimeToIdleSleep
2658 //
2659 // Returns number of milliseconds left before going into idle sleep.
2660 // Caller has to make sure that idle sleep is allowed at the time of calling
2661 // this function
2662 //******************************************************************************
2663 
2664 uint32_t
getTimeToIdleSleep(void)2665 IOPMrootDomain::getTimeToIdleSleep( void )
2666 {
2667 	AbsoluteTime    now, lastActivityTime;
2668 	uint64_t        nanos;
2669 	uint32_t        minutesSinceUserInactive = 0;
2670 	uint32_t        sleepDelay = 0;
2671 
2672 	if (!idleSleepEnabled) {
2673 		return 0xffffffff;
2674 	}
2675 
2676 	if (userActivityTime) {
2677 		lastActivityTime = userActivityTime;
2678 	} else {
2679 		lastActivityTime = userBecameInactiveTime;
2680 	}
2681 
2682 	// Ignore any lastActivityTime that predates the last system wake.
2683 	// The goal is to avoid a sudden idle sleep right after a dark wake
2684 	// due to sleepDelay=0 computed below. The alternative 60s minimum
2685 	// timeout should be large enough to allow dark wake to complete,
2686 	// at which point the idle timer will be promptly cancelled.
2687 	clock_get_uptime(&now);
2688 	if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2689 	    (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2690 		SUB_ABSOLUTETIME(&now, &lastActivityTime);
2691 		absolutetime_to_nanoseconds(now, &nanos);
2692 		minutesSinceUserInactive = nanos / (60000000000ULL);
2693 
2694 		if (minutesSinceUserInactive >= sleepSlider) {
2695 			sleepDelay = 0;
2696 		} else {
2697 			sleepDelay = sleepSlider - minutesSinceUserInactive;
2698 		}
2699 	} else {
2700 		DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2701 		    lastActivityTime, now, gIOLastWakeAbsTime);
2702 		sleepDelay = sleepSlider;
2703 	}
2704 
2705 	DLOG("user inactive %u min, time to idle sleep %u min\n",
2706 	    minutesSinceUserInactive, sleepDelay);
2707 
2708 	return sleepDelay * 60 * 1000;
2709 }
2710 
2711 //******************************************************************************
2712 // setQuickSpinDownTimeout
2713 //
2714 //******************************************************************************
2715 
2716 void
setQuickSpinDownTimeout(void)2717 IOPMrootDomain::setQuickSpinDownTimeout( void )
2718 {
2719 	ASSERT_GATED();
2720 	setAggressiveness(
2721 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2722 }
2723 
2724 //******************************************************************************
2725 // restoreUserSpinDownTimeout
2726 //
2727 //******************************************************************************
2728 
2729 void
restoreUserSpinDownTimeout(void)2730 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2731 {
2732 	ASSERT_GATED();
2733 	setAggressiveness(
2734 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2735 }
2736 
2737 //******************************************************************************
2738 // sleepSystem
2739 //
2740 //******************************************************************************
2741 
2742 /* public */
2743 IOReturn
sleepSystem(void)2744 IOPMrootDomain::sleepSystem( void )
2745 {
2746 	return sleepSystemOptions(NULL);
2747 }
2748 
2749 /* private */
2750 IOReturn
sleepSystemOptions(OSDictionary * options)2751 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2752 {
2753 	OSObject *obj = NULL;
2754 	OSString *reason = NULL;
2755 	/* sleepSystem is a public function, and may be called by any kernel driver.
2756 	 * And that's bad - drivers should sleep the system by calling
2757 	 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2758 	 *
2759 	 * Note that user space app calls to IOPMSleepSystem() will also travel
2760 	 * this code path and thus be correctly identified as software sleeps.
2761 	 */
2762 
2763 	if (options && options->getObject("OSSwitch")) {
2764 		// Log specific sleep cause for OS Switch hibernation
2765 		return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2766 	}
2767 
2768 	if (options && (obj = options->getObject("Sleep Reason"))) {
2769 		reason = OSDynamicCast(OSString, obj);
2770 		if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2771 			return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2772 		}
2773 		if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2774 			return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2775 		}
2776 	}
2777 
2778 	return privateSleepSystem( kIOPMSleepReasonSoftware);
2779 }
2780 
2781 /* private */
2782 IOReturn
privateSleepSystem(uint32_t sleepReason)2783 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2784 {
2785 	/* Called from both gated and non-gated context */
2786 
2787 	if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2788 		return kIOReturnNotPermitted;
2789 	}
2790 
2791 	pmPowerStateQueue->submitPowerEvent(
2792 		kPowerEventPolicyStimulus,
2793 		(void *) kStimulusDemandSystemSleep,
2794 		sleepReason);
2795 
2796 	return kIOReturnSuccess;
2797 }
2798 
2799 //******************************************************************************
2800 // powerChangeDone
2801 //
2802 // This overrides powerChangeDone in IOService.
2803 //******************************************************************************
2804 void
powerChangeDone(unsigned long previousPowerState)2805 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2806 {
2807 #if !__i386__ && !__x86_64__
2808 	uint64_t    timeSinceReset = 0;
2809 #endif
2810 	uint64_t           now;
2811 	unsigned long      newState;
2812 	clock_sec_t        secs;
2813 	clock_usec_t       microsecs;
2814 	uint32_t           lastDebugWakeSeconds;
2815 	clock_sec_t        adjWakeTime;
2816 	IOPMCalendarStruct nowCalendar;
2817 
2818 	ASSERT_GATED();
2819 	newState = getPowerState();
2820 	DLOG("PowerChangeDone: %s->%s\n",
2821 	    getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2822 
2823 	if (previousPowerState == newState) {
2824 		return;
2825 	}
2826 
2827 	notifierThread = current_thread();
2828 	switch (getPowerState()) {
2829 	case SLEEP_STATE: {
2830 		if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2831 			secs = 0;
2832 			microsecs = 0;
2833 			PEGetUTCTimeOfDay(&secs, &microsecs);
2834 
2835 			adjWakeTime = 0;
2836 			if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2837 				IOLog("use _calendarWakeAlarmUTC\n");
2838 				adjWakeTime = _calendarWakeAlarmUTC;
2839 			} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2840 				IOLog("accelerate _aotWakeTime for exit\n");
2841 				adjWakeTime = secs;
2842 			} else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2843 				IOLog("accelerate _aotWakeTime for assertion\n");
2844 				adjWakeTime = secs;
2845 			}
2846 			if (adjWakeTime) {
2847 				IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2848 			}
2849 
2850 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2851 			IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2852 
2853 			IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2854 			assert(kIOReturnSuccess == ret);
2855 		}
2856 		if (_aotLastWakeTime) {
2857 			_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2858 			if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2859 				strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2860 				    gWakeReasonString,
2861 				    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2862 			}
2863 		}
2864 		_aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2865 		if (_aotTimerScheduled) {
2866 			_aotTimerES->cancelTimeout();
2867 			_aotTimerScheduled = false;
2868 		}
2869 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2870 
2871 		// re-enable this timer for next sleep
2872 		cancelIdleSleepTimer();
2873 
2874 		if (clamshellExists) {
2875 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2876 			if (gClamshellFlags & kClamshell_WAR_58009435) {
2877 				// Disable clamshell sleep until system has completed full wake.
2878 				// This prevents a system sleep request (due to a clamshell close)
2879 				// from being queued until the end of system full wake - even if
2880 				// other clamshell disable bits outside of our control is wrong.
2881 				setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2882 			}
2883 #endif
2884 
2885 			// Log the last known clamshell state before system sleep
2886 			DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2887 			    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2888 			    desktopMode, acAdaptorConnected);
2889 		}
2890 
2891 		clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
2892 		logtime(secs);
2893 		gIOLastSleepTime.tv_sec  = secs;
2894 		gIOLastSleepTime.tv_usec = microsecs;
2895 		if (!_aotLastWakeTime) {
2896 			gIOLastUserSleepTime = gIOLastSleepTime;
2897 		}
2898 
2899 		gIOLastWakeTime.tv_sec = 0;
2900 		gIOLastWakeTime.tv_usec = 0;
2901 		gIOLastSleepAbsTime = now;
2902 
2903 		if (wake2DarkwakeDelay && sleepDelaysReport) {
2904 			clock_sec_t     wake2DarkwakeSecs, darkwake2SleepSecs;
2905 			// Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2906 
2907 			SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2908 			absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
2909 			absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
2910 			HISTREPORT_TALLYVALUE(sleepDelaysReport,
2911 			    (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2912 
2913 			DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2914 			wake2DarkwakeDelay = 0;
2915 		}
2916 #if HIBERNATION
2917 		LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2918 #if (DEVELOPMENT || DEBUG)
2919 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2920 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2921 		    "System State",
2922 		    gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2923 		    );
2924 #endif /* DEVELOPMENT || DEBUG */
2925 		IOHibernateSystemHasSlept();
2926 
2927 		evaluateSystemSleepPolicyFinal();
2928 #else
2929 		LOG("System Sleep\n");
2930 #if (DEVELOPMENT || DEBUG)
2931 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2932 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2933 		    "System State", "Enter Sleep");
2934 #endif /* DEVELOPMENT || DEBUG */
2935 #endif
2936 		if (thermalWarningState) {
2937 			OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2938 			if (event) {
2939 				systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2940 			}
2941 		}
2942 		assertOnWakeSecs = 0;
2943 		lowBatteryCondition = false;
2944 		thermalEmergencyState = false;
2945 
2946 #if DEVELOPMENT || DEBUG
2947 		extern int g_should_log_clock_adjustments;
2948 		if (g_should_log_clock_adjustments) {
2949 			clock_sec_t  secs = 0;
2950 			clock_usec_t microsecs = 0;
2951 			uint64_t now_b = mach_absolute_time();
2952 
2953 			secs = 0;
2954 			microsecs = 0;
2955 			PEGetUTCTimeOfDay(&secs, &microsecs);
2956 
2957 			uint64_t now_a = mach_absolute_time();
2958 			os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2959 			    __func__, (unsigned long)secs, microsecs, now_b, now_a);
2960 		}
2961 #endif
2962 
2963 		getPlatform()->sleepKernel();
2964 
2965 		// The CPU(s) are off at this point,
2966 		// Code will resume execution here upon wake.
2967 
2968 		clock_get_uptime(&gIOLastWakeAbsTime);
2969 		IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2970 #if DEVELOPMENT || DEBUG
2971 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2972 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2973 		    "System State", "Waking Up"
2974 		    );
2975 #endif /* DEVELOPMENT || DEBUG */
2976 		_highestCapability = 0;
2977 
2978 #if HIBERNATION
2979 		IOHibernateSystemWake();
2980 #endif
2981 
2982 		// sleep transition complete
2983 		gSleepOrShutdownPending = 0;
2984 
2985 		// trip the reset of the calendar clock
2986 		clock_wakeup_calendar();
2987 		clock_get_calendar_microtime(&secs, &microsecs);
2988 		gIOLastWakeTime.tv_sec  = secs;
2989 		gIOLastWakeTime.tv_usec = microsecs;
2990 
2991 		// aot
2992 		if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2993 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2994 			secs = 0;
2995 			microsecs = 0;
2996 			PEGetUTCTimeOfDay(&secs, &microsecs);
2997 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2998 			IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2999 			_aotMetrics->sleepCount++;
3000 			_aotLastWakeTime = gIOLastWakeAbsTime;
3001 			if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
3002 				_aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
3003 				        = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
3004 				_aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3005 				        = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3006 			}
3007 
3008 			if (_aotTestTime) {
3009 				if (_aotWakeTimeUTC <= secs) {
3010 					_aotTestTime = _aotTestTime + _aotTestInterval;
3011 				}
3012 				setWakeTime(_aotTestTime);
3013 			}
3014 		}
3015 
3016 #if HIBERNATION
3017 		LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3018 #endif
3019 
3020 		lastSleepReason = 0;
3021 
3022 		lastDebugWakeSeconds    = _debugWakeSeconds;
3023 		_debugWakeSeconds       = 0;
3024 		_scheduledAlarmMask     = 0;
3025 		_nextScheduledAlarmType = NULL;
3026 
3027 		darkWakeExit            = false;
3028 		darkWakePowerClamped    = false;
3029 		darkWakePostTickle      = false;
3030 		darkWakeHibernateError  = false;
3031 		darkWakeToSleepASAP     = true;
3032 		darkWakeLogClamp        = true;
3033 		sleepTimerMaintenance   = false;
3034 		sleepToStandby          = false;
3035 		wranglerTickled         = false;
3036 		userWasActive           = false;
3037 		isRTCAlarmWake          = false;
3038 		clamshellIgnoreClose    = false;
3039 		fullWakeReason = kFullWakeReasonNone;
3040 		idleSleepRevertible     = true;
3041 
3042 #if defined(__i386__) || defined(__x86_64__)
3043 		kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3044 
3045 		OSSharedPtr<OSObject> wakeTypeProp   = copyProperty(kIOPMRootDomainWakeTypeKey);
3046 		OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3047 		OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3048 		OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3049 
3050 		if (wakeReason && (wakeReason->getLength() >= 2) &&
3051 		    gWakeReasonString[0] == '\0') {
3052 			WAKEEVENT_LOCK();
3053 			// Until the platform driver can claim its wake reasons
3054 			strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3055 			    sizeof(gWakeReasonString));
3056 			if (!gWakeReasonSysctlRegistered) {
3057 				gWakeReasonSysctlRegistered = true;
3058 			}
3059 			WAKEEVENT_UNLOCK();
3060 		}
3061 
3062 		if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3063 			lowBatteryCondition = true;
3064 			darkWakeMaintenance = true;
3065 		} else {
3066 #if HIBERNATION
3067 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3068 			OSNumber * hibOptions = OSDynamicCast(  OSNumber, hibOptionsProp.get());
3069 			if (hibernateAborted || ((hibOptions &&
3070 			    !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3071 				// Hibernate aborted, or EFI brought up graphics
3072 				darkWakeExit = true;
3073 				if (hibernateAborted) {
3074 					DLOG("Hibernation aborted\n");
3075 				} else {
3076 					DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3077 				}
3078 			} else
3079 #endif
3080 			if (wakeType && (
3081 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3082 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3083 				// User wake or RTC alarm
3084 				darkWakeExit = true;
3085 				if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3086 					isRTCAlarmWake = true;
3087 				}
3088 			} else if (wakeType &&
3089 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3090 				// SMC standby timer trumps SleepX
3091 				darkWakeMaintenance = true;
3092 				sleepTimerMaintenance = true;
3093 			} else if ((lastDebugWakeSeconds != 0) &&
3094 			    ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3095 				// SleepX before maintenance
3096 				darkWakeExit = true;
3097 			} else if (wakeType &&
3098 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3099 				darkWakeMaintenance = true;
3100 			} else if (wakeType &&
3101 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3102 				darkWakeMaintenance = true;
3103 				darkWakeSleepService = true;
3104 #if HIBERNATION
3105 				if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3106 					sleepToStandby = true;
3107 				}
3108 #endif
3109 			} else if (wakeType &&
3110 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3111 				darkWakeMaintenance = true;
3112 				darkWakeHibernateError = true;
3113 			} else {
3114 				// Unidentified wake source, resume to full wake if debug
3115 				// alarm is pending.
3116 
3117 				if (lastDebugWakeSeconds &&
3118 				    (!wakeReason || wakeReason->isEqualTo(""))) {
3119 					darkWakeExit = true;
3120 				}
3121 			}
3122 		}
3123 
3124 		if (darkWakeExit) {
3125 			darkWakeToSleepASAP = false;
3126 			fullWakeReason = kFullWakeReasonLocalUser;
3127 			reportUserInput();
3128 		} else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3129 			handleSetDisplayPowerOn(true);
3130 		} else if (!darkWakeMaintenance) {
3131 			// Early/late tickle for non-maintenance wake.
3132 			if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3133 				darkWakePostTickle = true;
3134 			}
3135 		}
3136 #else   /* !__i386__ && !__x86_64__ */
3137 		timeSinceReset = ml_get_time_since_reset();
3138 		kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3139 
3140 		if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3141 			wranglerTickled = true;
3142 			fullWakeReason = kFullWakeReasonLocalUser;
3143 			requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3144 		} else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3145 			isRTCAlarmWake = true;
3146 			fullWakeReason = kFullWakeReasonLocalUser;
3147 			requestUserActive(this, "RTC debug alarm");
3148 		} else {
3149 #if HIBERNATION
3150 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3151 			OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3152 			if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3153 				fullWakeReason = kFullWakeReasonLocalUser;
3154 				requestUserActive(this, "hibernate user wake");
3155 			}
3156 #endif
3157 		}
3158 
3159 		// stay awake for at least 30 seconds
3160 		startIdleSleepTimer(30 * 1000);
3161 #endif
3162 		sleepCnt++;
3163 
3164 		thread_call_enter(updateConsoleUsersEntry);
3165 
3166 		// Skip AOT_STATE if we are waking up from an RTC timer.
3167 		// This check needs to be done after the epoch change is processed
3168 		// and before the changePowerStateWithTagToPriv() call below.
3169 		WAKEEVENT_LOCK();
3170 		aotShouldExit(false);
3171 		WAKEEVENT_UNLOCK();
3172 
3173 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3174 		break;
3175 	}
3176 #if !__i386__ && !__x86_64__
3177 	case ON_STATE:
3178 	case AOT_STATE:
3179 	{
3180 		DLOG("Force re-evaluating aggressiveness\n");
3181 		/* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3182 		pmPowerStateQueue->submitPowerEvent(
3183 			kPowerEventPolicyStimulus,
3184 			(void *) kStimulusNoIdleSleepPreventers );
3185 
3186 		// After changing to ON_STATE, invalidate any previously queued
3187 		// request to change to a state less than ON_STATE. This isn't
3188 		// necessary for AOT_STATE or if the device has only one running
3189 		// state since the changePowerStateToPriv() issued at the tail
3190 		// end of SLEEP_STATE case should take care of that.
3191 		if (getPowerState() == ON_STATE) {
3192 			changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3193 		}
3194 		break;
3195 	}
3196 #endif /* !__i386__ && !__x86_64__ */
3197 	}
3198 	notifierThread = NULL;
3199 }
3200 
3201 //******************************************************************************
3202 // requestPowerDomainState
3203 //
3204 // Extend implementation in IOService. Running on PM work loop thread.
3205 //******************************************************************************
3206 
3207 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3208 IOPMrootDomain::requestPowerDomainState(
3209 	IOPMPowerFlags      childDesire,
3210 	IOPowerConnection * childConnection,
3211 	unsigned long       specification )
3212 {
3213 	// Idle and system sleep prevention flags affects driver desire.
3214 	// Children desire are irrelevant so they are cleared.
3215 
3216 	return super::requestPowerDomainState(0, childConnection, specification);
3217 }
3218 
3219 
3220 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3221 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3222 {
3223 	if (!preventers->getCount()) {
3224 		return;
3225 	}
3226 
3227 	char *buf_iter = buf + strlen(buf);
3228 	char *buf_end = buf + buf_size;
3229 
3230 	OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3231 	OSObject *obj = NULL;
3232 
3233 	while ((obj = iterator->getNextObject())) {
3234 		IOService *srv = OSDynamicCast(IOService, obj);
3235 		if (buf_iter < buf_end) {
3236 			buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3237 		} else {
3238 			DLOG("Print buffer exhausted for sleep preventers list\n");
3239 			break;
3240 		}
3241 	}
3242 }
3243 
3244 //******************************************************************************
3245 // updatePreventIdleSleepList
3246 //
3247 // Called by IOService on PM work loop.
3248 // Returns true if PM policy recognized the driver's desire to prevent idle
3249 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3250 //******************************************************************************
3251 
3252 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3253 IOPMrootDomain::updatePreventIdleSleepList(
3254 	IOService * service, bool addNotRemove)
3255 {
3256 	unsigned int oldCount;
3257 
3258 	oldCount = idleSleepPreventersCount();
3259 	return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3260 }
3261 
3262 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3263 IOPMrootDomain::updatePreventIdleSleepListInternal(
3264 	IOService * service, bool addNotRemove, unsigned int oldCount)
3265 {
3266 	unsigned int newCount;
3267 
3268 	ASSERT_GATED();
3269 
3270 #if defined(XNU_TARGET_OS_OSX)
3271 	// Only the display wrangler and no-idle-sleep kernel assertions
3272 	// can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3273 	// reported by drivers in their power state table is ignored.
3274 	if (service && (service != wrangler) && (service != this)) {
3275 		return false;
3276 	}
3277 #endif
3278 
3279 	if (service) {
3280 		if (addNotRemove) {
3281 			preventIdleSleepList->setObject(service);
3282 			DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3283 			    service->getName(), preventIdleSleepList->getCount());
3284 		} else if (preventIdleSleepList->member(service)) {
3285 			preventIdleSleepList->removeObject(service);
3286 			DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3287 			    service->getName(), preventIdleSleepList->getCount());
3288 		}
3289 
3290 		if (preventIdleSleepList->getCount()) {
3291 			char buf[256] = "Idle Sleep Preventers:";
3292 			makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3293 			DLOG("%s\n", buf);
3294 		}
3295 	}
3296 
3297 	newCount = idleSleepPreventersCount();
3298 
3299 	if ((oldCount == 0) && (newCount != 0)) {
3300 		// Driver added to empty prevent list.
3301 		// Update the driver desire to prevent idle sleep.
3302 		// Driver desire does not prevent demand sleep.
3303 
3304 		changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3305 	} else if ((oldCount != 0) && (newCount == 0)) {
3306 		// Last driver removed from prevent list.
3307 		// Drop the driver clamp to allow idle sleep.
3308 
3309 		changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3310 		evaluatePolicy( kStimulusNoIdleSleepPreventers );
3311 	}
3312 	messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3313 	    &newCount, sizeof(newCount));
3314 
3315 #if defined(XNU_TARGET_OS_OSX)
3316 	if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3317 		DLOG("Cannot cancel idle sleep\n");
3318 		return false; // do not idle-cancel
3319 	}
3320 #endif
3321 
3322 	return true;
3323 }
3324 
3325 //******************************************************************************
3326 // startSpinDump
3327 //******************************************************************************
3328 
3329 void
startSpinDump(uint32_t spindumpKind)3330 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3331 {
3332 	messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3333 }
3334 
3335 //******************************************************************************
3336 // preventSystemSleepListUpdate
3337 //
3338 // Called by IOService on PM work loop.
3339 //******************************************************************************
3340 
3341 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3342 IOPMrootDomain::updatePreventSystemSleepList(
3343 	IOService * service, bool addNotRemove )
3344 {
3345 	unsigned int oldCount, newCount;
3346 
3347 	ASSERT_GATED();
3348 	if (this == service) {
3349 		return;
3350 	}
3351 
3352 	oldCount = preventSystemSleepList->getCount();
3353 	if (addNotRemove) {
3354 		preventSystemSleepList->setObject(service);
3355 		DLOG("Added %s to system sleep preventers list (Total %u)\n",
3356 		    service->getName(), preventSystemSleepList->getCount());
3357 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3358 			AbsoluteTime    now;
3359 			clock_usec_t    microsecs;
3360 			clock_get_uptime(&now);
3361 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3362 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
3363 			if (assertOnWakeReport) {
3364 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3365 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3366 			}
3367 		}
3368 	} else if (preventSystemSleepList->member(service)) {
3369 		preventSystemSleepList->removeObject(service);
3370 		DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3371 		    service->getName(), preventSystemSleepList->getCount());
3372 
3373 		if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3374 			// Lost all system sleep preventers.
3375 			// Send stimulus if system sleep was blocked, and is in dark wake.
3376 			evaluatePolicy( kStimulusDarkWakeEvaluate );
3377 		}
3378 	}
3379 
3380 	newCount = preventSystemSleepList->getCount();
3381 	if (newCount) {
3382 		char buf[256] = "System Sleep Preventers:";
3383 		makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3384 		DLOG("%s\n", buf);
3385 	}
3386 
3387 	messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3388 	    &newCount, sizeof(newCount));
3389 }
3390 
3391 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3392 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3393 {
3394 	OSSharedPtr<OSCollectionIterator> iterator;
3395 	OSObject    *object = NULL;
3396 	OSSharedPtr<OSArray>     array;
3397 
3398 	if (!gIOPMWorkLoop->inGate()) {
3399 		gIOPMWorkLoop->runAction(
3400 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3401 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3402 			this, (void *)idleSleepList, (void *)systemSleepList);
3403 		return;
3404 	}
3405 
3406 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3407 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3408 		array = OSArray::withCapacity(5);
3409 
3410 		if (iterator && array) {
3411 			while ((object = iterator->getNextObject())) {
3412 				IOService *service = OSDynamicCast(IOService, object);
3413 				if (service) {
3414 					OSSharedPtr<const OSSymbol> name = service->copyName();
3415 					if (name) {
3416 						array->setObject(name.get());
3417 					}
3418 				}
3419 			}
3420 		}
3421 		*idleSleepList = array.detach();
3422 	}
3423 
3424 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3425 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3426 		array = OSArray::withCapacity(5);
3427 
3428 		if (iterator && array) {
3429 			while ((object = iterator->getNextObject())) {
3430 				IOService *service = OSDynamicCast(IOService, object);
3431 				if (service) {
3432 					OSSharedPtr<const OSSymbol> name = service->copyName();
3433 					if (name) {
3434 						array->setObject(name.get());
3435 					}
3436 				}
3437 			}
3438 		}
3439 		*systemSleepList = array.detach();
3440 	}
3441 }
3442 
3443 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3444 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3445 {
3446 	OSSharedPtr<OSCollectionIterator> iterator;
3447 	OSObject    *object = NULL;
3448 	OSSharedPtr<OSArray>     array;
3449 
3450 	if (!gIOPMWorkLoop->inGate()) {
3451 		gIOPMWorkLoop->runAction(
3452 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3453 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3454 			this, (void *)idleSleepList, (void *)systemSleepList);
3455 		return;
3456 	}
3457 
3458 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3459 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3460 		array = OSArray::withCapacity(5);
3461 
3462 		if (iterator && array) {
3463 			while ((object = iterator->getNextObject())) {
3464 				IOService *service = OSDynamicCast(IOService, object);
3465 				if (service) {
3466 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3467 					OSSharedPtr<const OSSymbol> name = service->copyName();
3468 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3469 					if (dict && name && id) {
3470 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3471 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3472 						array->setObject(dict.get());
3473 					}
3474 				}
3475 			}
3476 		}
3477 		*idleSleepList = array.detach();
3478 	}
3479 
3480 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3481 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3482 		array = OSArray::withCapacity(5);
3483 
3484 		if (iterator && array) {
3485 			while ((object = iterator->getNextObject())) {
3486 				IOService *service = OSDynamicCast(IOService, object);
3487 				if (service) {
3488 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3489 					OSSharedPtr<const OSSymbol> name = service->copyName();
3490 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3491 					if (dict && name && id) {
3492 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3493 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3494 						array->setObject(dict.get());
3495 					}
3496 				}
3497 			}
3498 		}
3499 		*systemSleepList = array.detach();
3500 	}
3501 }
3502 
3503 //******************************************************************************
3504 // tellChangeDown
3505 //
3506 // Override the superclass implementation to send a different message type.
3507 //******************************************************************************
3508 
3509 bool
tellChangeDown(unsigned long stateNum)3510 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3511 {
3512 	DLOG("tellChangeDown %s->%s\n",
3513 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3514 
3515 	if (SLEEP_STATE == stateNum) {
3516 		// Legacy apps were already told in the full->dark transition
3517 		if (!ignoreTellChangeDown) {
3518 			tracePoint( kIOPMTracePointSleepApplications );
3519 		} else {
3520 			tracePoint( kIOPMTracePointSleepPriorityClients );
3521 		}
3522 	}
3523 
3524 	if (!ignoreTellChangeDown) {
3525 		userActivityAtSleep = userActivityCount;
3526 		DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3527 
3528 		if (SLEEP_STATE == stateNum) {
3529 			hibernateAborted = false;
3530 
3531 			// Direct callout into OSKext so it can disable kext unloads
3532 			// during sleep/wake to prevent deadlocks.
3533 			OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3534 
3535 			IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3536 
3537 			// Two change downs are sent by IOServicePM. Ignore the 2nd.
3538 			// But tellClientsWithResponse() must be called for both.
3539 			ignoreTellChangeDown = true;
3540 		}
3541 	}
3542 
3543 	return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3544 }
3545 
3546 //******************************************************************************
3547 // askChangeDown
3548 //
3549 // Override the superclass implementation to send a different message type.
3550 // This must be idle sleep since we don't ask during any other power change.
3551 //******************************************************************************
3552 
3553 bool
askChangeDown(unsigned long stateNum)3554 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3555 {
3556 	DLOG("askChangeDown %s->%s\n",
3557 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3558 
3559 	// Don't log for dark wake entry
3560 	if (kSystemTransitionSleep == _systemTransitionType) {
3561 		tracePoint( kIOPMTracePointSleepApplications );
3562 	}
3563 
3564 	return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3565 }
3566 
3567 //******************************************************************************
3568 // askChangeDownDone
3569 //
3570 // An opportunity for root domain to cancel the power transition,
3571 // possibily due to an assertion created by powerd in response to
3572 // kIOMessageCanSystemSleep.
3573 //
3574 // Idle sleep:
3575 //   full -> dark wake transition
3576 //     1. Notify apps and powerd with kIOMessageCanSystemSleep
3577 //     2. askChangeDownDone()
3578 //   dark -> sleep transition
3579 //     1. Notify powerd with kIOMessageCanSystemSleep
3580 //     2. askChangeDownDone()
3581 //
3582 // Demand sleep:
3583 //   full -> dark wake transition
3584 //     1. Notify powerd with kIOMessageCanSystemSleep
3585 //     2. askChangeDownDone()
3586 //   dark -> sleep transition
3587 //     1. Notify powerd with kIOMessageCanSystemSleep
3588 //     2. askChangeDownDone()
3589 //******************************************************************************
3590 
3591 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3592 IOPMrootDomain::askChangeDownDone(
3593 	IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3594 {
3595 	DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3596 	    *inOutChangeFlags, *cancel,
3597 	    _systemTransitionType,
3598 	    _currentCapability, _pendingCapability);
3599 
3600 	if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3601 		// Dark->Sleep transition.
3602 		// Check if there are any deny sleep assertions.
3603 		// lastSleepReason already set by handleOurPowerChangeStart()
3604 
3605 		if (!checkSystemCanSleep(lastSleepReason)) {
3606 			// Cancel dark wake to sleep transition.
3607 			// Must re-scan assertions upon entering dark wake.
3608 
3609 			*cancel = true;
3610 			DLOG("cancel dark->sleep\n");
3611 		}
3612 		if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3613 			uint64_t now = mach_continuous_time();
3614 			if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3615 			    && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3616 				*cancel = true;
3617 				IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3618 			}
3619 		}
3620 	}
3621 }
3622 
3623 //******************************************************************************
3624 // systemDidNotSleep
3625 //
3626 // Work common to both canceled or aborted sleep.
3627 //******************************************************************************
3628 
3629 void
systemDidNotSleep(void)3630 IOPMrootDomain::systemDidNotSleep( void )
3631 {
3632 	// reset console lock state
3633 	thread_call_enter(updateConsoleUsersEntry);
3634 
3635 	if (idleSleepEnabled) {
3636 		if (!wrangler) {
3637 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3638 			startIdleSleepTimer(kIdleSleepRetryInterval);
3639 #else
3640 			startIdleSleepTimer(idleMilliSeconds);
3641 #endif
3642 		} else if (!userIsActive) {
3643 			// Manually start the idle sleep timer besides waiting for
3644 			// the user to become inactive.
3645 			startIdleSleepTimer(kIdleSleepRetryInterval);
3646 		}
3647 	}
3648 
3649 	preventTransitionToUserActive(false);
3650 	IOService::setAdvisoryTickleEnable( true );
3651 	idleSleepRevertible = true;
3652 
3653 	// After idle revert and cancel, send a did-change message to powerd
3654 	// to balance the previous will-change message. Kernel clients do not
3655 	// need this since sleep cannot be canceled once they are notified.
3656 
3657 	if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3658 	    (_pendingCapability != _currentCapability) &&
3659 	    ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3660 		// Differs from a real capability gain change where notifyRef != 0,
3661 		// but it is zero here since no response is expected.
3662 
3663 		IOPMSystemCapabilityChangeParameters params;
3664 
3665 		bzero(&params, sizeof(params));
3666 		params.fromCapabilities = _pendingCapability;
3667 		params.toCapabilities = _currentCapability;
3668 		params.changeFlags = kIOPMSystemCapabilityDidChange;
3669 
3670 		DLOG("MESG cap %x->%x did change\n",
3671 		    params.fromCapabilities, params.toCapabilities);
3672 		messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3673 		    &params, sizeof(params));
3674 	}
3675 }
3676 
3677 //******************************************************************************
3678 // tellNoChangeDown
3679 //
3680 // Notify registered applications and kernel clients that we are not dropping
3681 // power.
3682 //
3683 // We override the superclass implementation so we can send a different message
3684 // type to the client or application being notified.
3685 //
3686 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3687 //******************************************************************************
3688 
3689 void
tellNoChangeDown(unsigned long stateNum)3690 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3691 {
3692 	DLOG("tellNoChangeDown %s->%s\n",
3693 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3694 
3695 	// Sleep canceled, clear the sleep trace point.
3696 	tracePoint(kIOPMTracePointSystemUp);
3697 
3698 	systemDidNotSleep();
3699 	return tellClients( kIOMessageSystemWillNotSleep );
3700 }
3701 
3702 //******************************************************************************
3703 // tellChangeUp
3704 //
3705 // Notify registered applications and kernel clients that we are raising power.
3706 //
3707 // We override the superclass implementation so we can send a different message
3708 // type to the client or application being notified.
3709 //******************************************************************************
3710 
3711 void
tellChangeUp(unsigned long stateNum)3712 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3713 {
3714 	DLOG("tellChangeUp %s->%s\n",
3715 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3716 
3717 	ignoreTellChangeDown = false;
3718 
3719 	if (stateNum == ON_STATE) {
3720 		// Direct callout into OSKext so it can disable kext unloads
3721 		// during sleep/wake to prevent deadlocks.
3722 		OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3723 
3724 		// Notify platform that sleep was cancelled or resumed.
3725 		getPlatform()->callPlatformFunction(
3726 			sleepMessagePEFunction.get(), false,
3727 			(void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3728 			NULL, NULL, NULL);
3729 
3730 		if (getPowerState() == ON_STATE) {
3731 			// Sleep was cancelled by idle cancel or revert
3732 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3733 				// rdar://problem/50363791
3734 				// If system is in dark wake and sleep is cancelled, do not
3735 				// send SystemWillPowerOn/HasPoweredOn messages to kernel
3736 				// priority clients. They haven't yet seen a SystemWillSleep
3737 				// message before the cancellation. So make sure the kernel
3738 				// client bit is cleared in _systemMessageClientMask before
3739 				// invoking the tellClients() below. This bit may have been
3740 				// set by handleOurPowerChangeStart() anticipating a successful
3741 				// sleep and setting the filter mask ahead of time allows the
3742 				// SystemWillSleep message to go through.
3743 				_systemMessageClientMask &= ~kSystemMessageClientKernel;
3744 			}
3745 
3746 			systemDidNotSleep();
3747 			tellClients( kIOMessageSystemWillPowerOn );
3748 		}
3749 
3750 		tracePoint( kIOPMTracePointWakeApplications );
3751 		tellClients( kIOMessageSystemHasPoweredOn );
3752 	} else if (stateNum == AOT_STATE) {
3753 		if (getPowerState() == AOT_STATE) {
3754 			// Sleep was cancelled by idle cancel or revert
3755 			startIdleSleepTimer(idleMilliSeconds);
3756 		}
3757 	}
3758 }
3759 
3760 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3761     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3762      ((params)->fromCapabilities & (flag)) && \
3763      (((params)->toCapabilities & (flag)) == 0))
3764 
3765 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3766     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3767      ((params)->toCapabilities & (flag)) && \
3768      (((params)->fromCapabilities & (flag)) == 0))
3769 
3770 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3771     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3772      ((params)->fromCapabilities & (flag)) && \
3773      (((params)->toCapabilities & (flag)) == 0))
3774 
3775 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3776     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3777      ((params)->toCapabilities & (flag)) && \
3778      (((params)->fromCapabilities & (flag)) == 0))
3779 
3780 //******************************************************************************
3781 // sysPowerDownHandler
3782 //
3783 // Perform a vfs sync before system sleep.
3784 //******************************************************************************
3785 
3786 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3787 IOPMrootDomain::sysPowerDownHandler(
3788 	void * target, void * refCon,
3789 	UInt32 messageType, IOService * service,
3790 	void * messageArgs, vm_size_t argSize )
3791 {
3792 	static UInt32 lastSystemMessageType = 0;
3793 	IOReturn    ret = 0;
3794 
3795 	DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3796 
3797 	// rdar://problem/50363791
3798 	// Sanity check to make sure the SystemWill/Has message types are
3799 	// received in the expected order for all kernel priority clients.
3800 	if (messageType == kIOMessageSystemWillSleep ||
3801 	    messageType == kIOMessageSystemWillPowerOn ||
3802 	    messageType == kIOMessageSystemHasPoweredOn) {
3803 		switch (messageType) {
3804 		case kIOMessageSystemWillPowerOn:
3805 			assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3806 			break;
3807 		case kIOMessageSystemHasPoweredOn:
3808 			assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3809 			break;
3810 		}
3811 
3812 		lastSystemMessageType = messageType;
3813 	}
3814 
3815 	if (!gRootDomain) {
3816 		return kIOReturnUnsupported;
3817 	}
3818 
3819 	if (messageType == kIOMessageSystemCapabilityChange) {
3820 		IOPMSystemCapabilityChangeParameters * params =
3821 		    (IOPMSystemCapabilityChangeParameters *) messageArgs;
3822 
3823 		// Interested applications have been notified of an impending power
3824 		// change and have acked (when applicable).
3825 		// This is our chance to save whatever state we can before powering
3826 		// down.
3827 		// We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3828 		// via callout
3829 
3830 		DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3831 		    params->fromCapabilities, params->toCapabilities,
3832 		    params->changeFlags);
3833 
3834 		if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3835 			// We will ack within 20 seconds
3836 			params->maxWaitForReply = 20 * 1000 * 1000;
3837 
3838 #if HIBERNATION
3839 			gRootDomain->evaluateSystemSleepPolicyEarly();
3840 
3841 			// add in time we could spend freeing pages
3842 			if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3843 				params->maxWaitForReply = kCapabilityClientMaxWait;
3844 			}
3845 			DLOG("sysPowerDownHandler max wait %d s\n",
3846 			    (int) (params->maxWaitForReply / 1000 / 1000));
3847 #endif
3848 
3849 			// Notify platform that sleep has begun, after the early
3850 			// sleep policy evaluation.
3851 			getPlatform()->callPlatformFunction(
3852 				sleepMessagePEFunction.get(), false,
3853 				(void *)(uintptr_t) kIOMessageSystemWillSleep,
3854 				NULL, NULL, NULL);
3855 
3856 			if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3857 				// Purposely delay the ack and hope that shutdown occurs quickly.
3858 				// Another option is not to schedule the thread and wait for
3859 				// ack timeout...
3860 				AbsoluteTime deadline;
3861 				clock_interval_to_deadline( 30, kSecondScale, &deadline );
3862 				thread_call_enter1_delayed(
3863 					gRootDomain->diskSyncCalloutEntry,
3864 					(thread_call_param_t)(uintptr_t) params->notifyRef,
3865 					deadline );
3866 			} else {
3867 				thread_call_enter1(
3868 					gRootDomain->diskSyncCalloutEntry,
3869 					(thread_call_param_t)(uintptr_t) params->notifyRef);
3870 			}
3871 		}
3872 #if HIBERNATION
3873 		else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3874 			// We will ack within 110 seconds
3875 			params->maxWaitForReply = 110 * 1000 * 1000;
3876 
3877 			thread_call_enter1(
3878 				gRootDomain->diskSyncCalloutEntry,
3879 				(thread_call_param_t)(uintptr_t) params->notifyRef);
3880 		}
3881 #endif
3882 		ret = kIOReturnSuccess;
3883 	}
3884 
3885 	return ret;
3886 }
3887 
3888 //******************************************************************************
3889 // handleQueueSleepWakeUUID
3890 //
3891 // Called from IOPMrootDomain when we're initiating a sleep,
3892 // or indirectly from PM configd when PM decides to clear the UUID.
3893 // PM clears the UUID several minutes after successful wake from sleep,
3894 // so that we might associate App spindumps with the immediately previous
3895 // sleep/wake.
3896 //
3897 // @param   obj has a retain on it. We're responsible for releasing that retain.
3898 //******************************************************************************
3899 
3900 void
handleQueueSleepWakeUUID(OSObject * obj)3901 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3902 {
3903 	OSSharedPtr<OSString>    str;
3904 
3905 	if (kOSBooleanFalse == obj) {
3906 		handlePublishSleepWakeUUID(false);
3907 	} else {
3908 		str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3909 		if (str) {
3910 			// This branch caches the UUID for an upcoming sleep/wake
3911 			queuedSleepWakeUUIDString = str;
3912 			DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3913 		}
3914 	}
3915 }
3916 //******************************************************************************
3917 // handlePublishSleepWakeUUID
3918 //
3919 // Called from IOPMrootDomain when we're initiating a sleep,
3920 // or indirectly from PM configd when PM decides to clear the UUID.
3921 // PM clears the UUID several minutes after successful wake from sleep,
3922 // so that we might associate App spindumps with the immediately previous
3923 // sleep/wake.
3924 //******************************************************************************
3925 
3926 void
handlePublishSleepWakeUUID(bool shouldPublish)3927 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3928 {
3929 	ASSERT_GATED();
3930 
3931 	/*
3932 	 * Clear the current UUID
3933 	 */
3934 	if (gSleepWakeUUIDIsSet) {
3935 		DLOG("SleepWake UUID cleared\n");
3936 
3937 		gSleepWakeUUIDIsSet = false;
3938 
3939 		removeProperty(kIOPMSleepWakeUUIDKey);
3940 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3941 	}
3942 
3943 	/*
3944 	 * Optionally, publish a new UUID
3945 	 */
3946 	if (queuedSleepWakeUUIDString && shouldPublish) {
3947 		OSSharedPtr<OSString> publishThisUUID;
3948 
3949 		publishThisUUID = queuedSleepWakeUUIDString;
3950 
3951 		if (publishThisUUID) {
3952 			setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3953 		}
3954 
3955 		gSleepWakeUUIDIsSet = true;
3956 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3957 
3958 		queuedSleepWakeUUIDString.reset();
3959 	}
3960 }
3961 
3962 //******************************************************************************
3963 // IOPMGetSleepWakeUUIDKey
3964 //
3965 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3966 // To get the full key -- a C string -- the buffer must large enough for
3967 // the end-of-string character.
3968 // The key is expected to be an UUID string
3969 //******************************************************************************
3970 
3971 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3972 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3973 {
3974 	if (!gSleepWakeUUIDIsSet) {
3975 		return false;
3976 	}
3977 
3978 	if (buffer != NULL) {
3979 		OSSharedPtr<OSString> string =
3980 		    OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3981 
3982 		if (!string) {
3983 			*buffer = '\0';
3984 		} else {
3985 			strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3986 		}
3987 	}
3988 
3989 	return true;
3990 }
3991 
3992 //******************************************************************************
3993 // lowLatencyAudioNotify
3994 //
3995 // Used to send an update about low latency audio activity to interested
3996 // clients. To keep the overhead minimal the OSDictionary used here
3997 // is initialized at boot.
3998 //******************************************************************************
3999 
4000 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)4001 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
4002 {
4003 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
4004 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
4005 		lowLatencyAudioNotifyTimestampVal->setValue(time);
4006 		lowLatencyAudioNotifyStateVal->setValue(state);
4007 		setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4008 	} else {
4009 		DLOG("LowLatencyAudioNotify error\n");
4010 	}
4011 	return;
4012 }
4013 
4014 //******************************************************************************
4015 // IOPMrootDomainRTNotifier
4016 //
4017 // Used by performance controller to update the timestamp and state associated
4018 // with low latency audio activity in the system.
4019 //******************************************************************************
4020 
4021 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4022 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4023 {
4024 	gRootDomain->lowLatencyAudioNotify(time, state);
4025 	return;
4026 }
4027 
4028 //******************************************************************************
4029 // initializeBootSessionUUID
4030 //
4031 // Initialize the boot session uuid at boot up and sets it into registry.
4032 //******************************************************************************
4033 
4034 void
initializeBootSessionUUID(void)4035 IOPMrootDomain::initializeBootSessionUUID(void)
4036 {
4037 	uuid_t          new_uuid;
4038 	uuid_string_t   new_uuid_string;
4039 
4040 	uuid_generate(new_uuid);
4041 	uuid_unparse_upper(new_uuid, new_uuid_string);
4042 	memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4043 
4044 	setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4045 }
4046 
4047 //******************************************************************************
4048 // Root domain uses the private and tagged changePowerState methods for
4049 // tracking and logging purposes.
4050 //******************************************************************************
4051 
4052 #define REQUEST_TAG_TO_REASON(x)        ((uint16_t)x)
4053 
4054 static uint32_t
nextRequestTag(IOPMRequestTag tag)4055 nextRequestTag( IOPMRequestTag tag )
4056 {
4057 	static SInt16 msb16 = 1;
4058 	uint16_t id = OSAddAtomic16(1, &msb16);
4059 	return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4060 }
4061 
4062 // TODO: remove this shim function and exported symbol
4063 IOReturn
changePowerStateTo(unsigned long ordinal)4064 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4065 {
4066 	return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4067 }
4068 
4069 // TODO: remove this shim function and exported symbol
4070 IOReturn
changePowerStateToPriv(unsigned long ordinal)4071 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4072 {
4073 	return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4074 }
4075 
4076 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4077 IOPMrootDomain::changePowerStateWithOverrideTo(
4078 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4079 {
4080 	uint32_t tag = nextRequestTag(reason);
4081 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4082 
4083 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4084 		return kIOReturnUnsupported;
4085 	}
4086 
4087 	return super::changePowerStateWithOverrideTo(ordinal, tag);
4088 }
4089 
4090 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4091 IOPMrootDomain::changePowerStateWithTagTo(
4092 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4093 {
4094 	uint32_t tag = nextRequestTag(reason);
4095 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4096 
4097 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4098 		return kIOReturnUnsupported;
4099 	}
4100 
4101 	return super::changePowerStateWithTagTo(ordinal, tag);
4102 }
4103 
4104 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4105 IOPMrootDomain::changePowerStateWithTagToPriv(
4106 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4107 {
4108 	uint32_t tag = nextRequestTag(reason);
4109 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4110 
4111 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4112 		return kIOReturnUnsupported;
4113 	}
4114 
4115 	return super::changePowerStateWithTagToPriv(ordinal, tag);
4116 }
4117 
4118 //******************************************************************************
4119 // activity detect
4120 //
4121 //******************************************************************************
4122 
4123 bool
activitySinceSleep(void)4124 IOPMrootDomain::activitySinceSleep(void)
4125 {
4126 	return userActivityCount != userActivityAtSleep;
4127 }
4128 
4129 bool
abortHibernation(void)4130 IOPMrootDomain::abortHibernation(void)
4131 {
4132 #if __arm64__
4133 	// don't allow hibernation to be aborted on ARM due to user activity
4134 	// since once ApplePMGR decides we're hibernating, we can't turn back
4135 	// see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4136 	return false;
4137 #else
4138 	bool ret = activitySinceSleep();
4139 
4140 	if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4141 		DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4142 		hibernateAborted = true;
4143 	}
4144 	return ret;
4145 #endif
4146 }
4147 
4148 extern "C" int
hibernate_should_abort(void)4149 hibernate_should_abort(void)
4150 {
4151 	if (gRootDomain) {
4152 		return gRootDomain->abortHibernation();
4153 	} else {
4154 		return 0;
4155 	}
4156 }
4157 
4158 //******************************************************************************
4159 // scheduleImmediateDebugWake
4160 //
4161 // Schedule a wake with RTC to wake us back up immediately after we sleep.
4162 // Useful when a cancel request comes in past the revert point on the sleep path
4163 //******************************************************************************
4164 
4165 void
scheduleImmediateDebugWake(void)4166 IOPMrootDomain::scheduleImmediateDebugWake( void )
4167 {
4168 	OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(1);
4169 	OSSharedPtr<OSNumber> secs = OSNumber::withNumber(1, 32);
4170 
4171 	if (dict && secs) {
4172 		dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4173 		gRootDomain->setProperties(dict.get());
4174 		MSG("Reverting sleep with relative wake\n");
4175 	}
4176 }
4177 
4178 //******************************************************************************
4179 // willNotifyPowerChildren
4180 //
4181 // Called after all interested drivers have all acknowledged the power change,
4182 // but before any power children is informed. Dispatched though a thread call,
4183 // so it is safe to perform work that might block on a sleeping disk. PM state
4184 // machine (not thread) will block w/o timeout until this function returns.
4185 //******************************************************************************
4186 
4187 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4188 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4189 {
4190 	if (SLEEP_STATE == newPowerState) {
4191 		notifierThread = current_thread();
4192 		if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4193 			AbsoluteTime deadline;
4194 
4195 			clock_interval_to_deadline(10, kSecondScale, &deadline);
4196 #if defined(XNU_TARGET_OS_OSX)
4197 			vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4198 #endif /* defined(XNU_TARGET_OS_OSX) */
4199 		}
4200 
4201 		_aotReadyToFullWake = false;
4202 #if 0
4203 		if (_aotLingerTime) {
4204 			uint64_t deadline;
4205 			IOLog("aot linger no return\n");
4206 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4207 			clock_delay_until(deadline);
4208 		}
4209 #endif
4210 		if (!_aotMode) {
4211 			_aotTestTime = 0;
4212 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4213 			_aotLastWakeTime = 0;
4214 			if (_aotMetrics) {
4215 				bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4216 			}
4217 		} else if (!_aotNow && !_debugWakeSeconds) {
4218 			_aotNow            = true;
4219 			_aotPendingFlags   = 0;
4220 			_aotTasksSuspended = true;
4221 			_aotLastWakeTime   = 0;
4222 			bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4223 			if (kIOPMAOTModeCycle & _aotMode) {
4224 				clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4225 				_aotTestTime = mach_continuous_time() + _aotTestInterval;
4226 				setWakeTime(_aotTestTime);
4227 			}
4228 			uint32_t lingerSecs;
4229 			if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4230 				lingerSecs = 0;
4231 			}
4232 			clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4233 			clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4234 			clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4235 		}
4236 
4237 #if HIBERNATION
4238 		// Adjust watchdog for IOHibernateSystemSleep
4239 		int defaultTimeout = getWatchdogTimeout();
4240 		int timeout = defaultTimeout > WATCHDOG_HIBERNATION_TIMEOUT ?
4241 		    defaultTimeout : WATCHDOG_HIBERNATION_TIMEOUT;
4242 		reset_watchdog_timer(timeout);
4243 
4244 		IOHibernateSystemSleep();
4245 		IOHibernateIOKitSleep();
4246 #endif
4247 #if defined(__arm64__) && HIBERNATION
4248 		if (gIOHibernateState == kIOHibernateStateInactive) {
4249 			setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
4250 		}
4251 		// On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4252 		// user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4253 		// alarms, which can mess with cycler tools.
4254 		if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4255 #else /* defined(__arm64__) && HIBERNATION */
4256 		// On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4257 		// RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4258 		if (gRootDomain->activitySinceSleep()) {
4259 #endif /* defined(__arm64__) && HIBERNATION */
4260 			scheduleImmediateDebugWake();
4261 		}
4262 
4263 		notifierThread = NULL;
4264 	}
4265 }
4266 
4267 //******************************************************************************
4268 // willTellSystemCapabilityDidChange
4269 //
4270 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4271 // domain is raising its power state, immediately after notifying interested
4272 // drivers and power children.
4273 //******************************************************************************
4274 
4275 void
4276 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4277 {
4278 	if ((_systemTransitionType == kSystemTransitionWake) &&
4279 	    !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4280 		// After powering up drivers, dark->full promotion on the current wake
4281 		// transition is no longer possible. That is because the next machine
4282 		// state will issue the system capability change messages.
4283 		// The darkWakePowerClamped flag may already be set if the system has
4284 		// at least one driver that was power clamped due to dark wake.
4285 		// This function sets the darkWakePowerClamped flag in case there
4286 		// is no power-clamped driver in the system.
4287 		//
4288 		// Last opportunity to exit dark wake using:
4289 		// requestFullWake( kFullWakeReasonLocalUser );
4290 
4291 		if (!darkWakePowerClamped) {
4292 			if (darkWakeLogClamp) {
4293 				AbsoluteTime    now;
4294 				uint64_t        nsec;
4295 
4296 				clock_get_uptime(&now);
4297 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4298 				absolutetime_to_nanoseconds(now, &nsec);
4299 				DLOG("dark wake promotion disabled at %u ms\n",
4300 				    ((int)((nsec) / NSEC_PER_MSEC)));
4301 			}
4302 			darkWakePowerClamped = true;
4303 		}
4304 	}
4305 }
4306 
4307 //******************************************************************************
4308 // sleepOnClamshellClosed
4309 //
4310 // contains the logic to determine if the system should sleep when the clamshell
4311 // is closed.
4312 //******************************************************************************
4313 
4314 bool
4315 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4316 {
4317 	if (!clamshellExists) {
4318 		return false;
4319 	}
4320 
4321 	DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4322 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4323 
4324 	return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4325 }
4326 
4327 bool
4328 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4329 {
4330 	// Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4331 	// closed && battery
4332 	if (!clamshellExists) {
4333 		return false;
4334 	}
4335 
4336 	DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4337 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4338 
4339 	return !acAdaptorConnected && !clamshellSleepDisableMask;
4340 }
4341 
4342 void
4343 IOPMrootDomain::sendClientClamshellNotification( void )
4344 {
4345 	/* Only broadcast clamshell alert if clamshell exists. */
4346 	if (!clamshellExists) {
4347 		return;
4348 	}
4349 
4350 	setProperty(kAppleClamshellStateKey,
4351 	    clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4352 
4353 	setProperty(kAppleClamshellCausesSleepKey,
4354 	    shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4355 
4356 	/* Argument to message is a bitfiel of
4357 	 *      ( kClamshellStateBit | kClamshellSleepBit )
4358 	 */
4359 	messageClients(kIOPMMessageClamshellStateChange,
4360 	    (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4361 	    | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4362 }
4363 
4364 //******************************************************************************
4365 // getSleepSupported
4366 //
4367 // Deprecated
4368 //******************************************************************************
4369 
4370 IOOptionBits
4371 IOPMrootDomain::getSleepSupported( void )
4372 {
4373 	return platformSleepSupport;
4374 }
4375 
4376 //******************************************************************************
4377 // setSleepSupported
4378 //
4379 // Deprecated
4380 //******************************************************************************
4381 
4382 void
4383 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4384 {
4385 	DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4386 	OSBitOrAtomic(flags, &platformSleepSupport);
4387 }
4388 
4389 //******************************************************************************
4390 // setClamShellSleepDisable
4391 //
4392 //******************************************************************************
4393 
4394 void
4395 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4396 {
4397 	uint32_t oldMask;
4398 
4399 	// User client calls this in non-gated context
4400 	if (gIOPMWorkLoop->inGate() == false) {
4401 		gIOPMWorkLoop->runAction(
4402 			OSMemberFunctionCast(IOWorkLoop::Action, this,
4403 			&IOPMrootDomain::setClamShellSleepDisable),
4404 			(OSObject *) this,
4405 			(void *) disable, (void *)(uintptr_t) bitmask);
4406 		return;
4407 	}
4408 
4409 	oldMask = clamshellSleepDisableMask;
4410 	if (disable) {
4411 		clamshellSleepDisableMask |= bitmask;
4412 	} else {
4413 		clamshellSleepDisableMask &= ~bitmask;
4414 	}
4415 	DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4416 
4417 	if (clamshellExists && clamshellClosed &&
4418 	    (clamshellSleepDisableMask != oldMask) &&
4419 	    (clamshellSleepDisableMask == 0)) {
4420 		handlePowerNotification(kLocalEvalClamshellCommand);
4421 	}
4422 }
4423 
4424 //******************************************************************************
4425 // wakeFromDoze
4426 //
4427 // Deprecated.
4428 //******************************************************************************
4429 
4430 void
4431 IOPMrootDomain::wakeFromDoze( void )
4432 {
4433 	// Preserve symbol for familes (IOUSBFamily and IOGraphics)
4434 }
4435 
4436 //******************************************************************************
4437 // recordRTCAlarm
4438 //
4439 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4440 // should be a dark wake or a full wake. Both Maintenance and SleepService
4441 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4442 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4443 // PMSettings are ignored.
4444 //
4445 // Caller serialized using settingsCtrlLock.
4446 //******************************************************************************
4447 
4448 void
4449 IOPMrootDomain::recordRTCAlarm(
4450 	const OSSymbol  *type,
4451 	OSObject        *object )
4452 {
4453 	uint32_t previousAlarmMask = _scheduledAlarmMask;
4454 
4455 	if (type == gIOPMSettingDebugWakeRelativeKey) {
4456 		OSNumber * n = OSDynamicCast(OSNumber, object);
4457 		if (n) {
4458 			// Debug wake has highest scheduling priority so it overrides any
4459 			// pre-existing alarm.
4460 			uint32_t debugSecs = n->unsigned32BitValue();
4461 			_nextScheduledAlarmType.reset(type, OSRetain);
4462 			_nextScheduledAlarmUTC = debugSecs;
4463 
4464 			_debugWakeSeconds = debugSecs;
4465 			OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4466 			DLOG("next alarm (%s) in %u secs\n",
4467 			    type->getCStringNoCopy(), debugSecs);
4468 		}
4469 	} else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4470 	    (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4471 	    (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4472 		OSData * data = OSDynamicCast(OSData, object);
4473 		if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4474 			const IOPMCalendarStruct * cs;
4475 			bool replaceNextAlarm = false;
4476 			clock_sec_t secs;
4477 
4478 			cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4479 			secs = IOPMConvertCalendarToSeconds(cs);
4480 			DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4481 
4482 			// Update the next scheduled alarm type
4483 			if ((_nextScheduledAlarmType == NULL) ||
4484 			    ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4485 			    (secs < _nextScheduledAlarmUTC))) {
4486 				replaceNextAlarm = true;
4487 			}
4488 
4489 			if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4490 				if (cs->year) {
4491 					_calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4492 					OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4493 				} else {
4494 					// TODO: can this else-block be removed?
4495 					_calendarWakeAlarmUTC = 0;
4496 					OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4497 				}
4498 			}
4499 			if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4500 				OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4501 			}
4502 			if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4503 				OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4504 			}
4505 
4506 			if (replaceNextAlarm) {
4507 				_nextScheduledAlarmType.reset(type, OSRetain);
4508 				_nextScheduledAlarmUTC = secs;
4509 				DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4510 			}
4511 		}
4512 	}
4513 
4514 	if (_scheduledAlarmMask != previousAlarmMask) {
4515 		DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4516 	}
4517 }
4518 
4519 // MARK: -
4520 // MARK: Features
4521 
4522 //******************************************************************************
4523 // publishFeature
4524 //
4525 // Adds a new feature to the supported features dictionary
4526 //******************************************************************************
4527 
4528 void
4529 IOPMrootDomain::publishFeature( const char * feature )
4530 {
4531 	publishFeature(feature, kRD_AllPowerSources, NULL);
4532 }
4533 
4534 //******************************************************************************
4535 // publishFeature (with supported power source specified)
4536 //
4537 // Adds a new feature to the supported features dictionary
4538 //******************************************************************************
4539 
4540 void
4541 IOPMrootDomain::publishFeature(
4542 	const char *feature,
4543 	uint32_t supportedWhere,
4544 	uint32_t *uniqueFeatureID)
4545 {
4546 	static uint16_t       next_feature_id = 500;
4547 
4548 	OSSharedPtr<OSNumber> new_feature_data;
4549 	OSNumber             *existing_feature = NULL;
4550 	OSArray              *existing_feature_arr_raw = NULL;
4551 	OSSharedPtr<OSArray>  existing_feature_arr;
4552 	OSObject             *osObj = NULL;
4553 	uint32_t              feature_value = 0;
4554 
4555 	supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4556 
4557 	if (!supportedWhere) {
4558 		// Feature isn't supported anywhere!
4559 		return;
4560 	}
4561 
4562 	if (next_feature_id > 5000) {
4563 		// Far, far too many features!
4564 		return;
4565 	}
4566 
4567 	if (featuresDictLock) {
4568 		IOLockLock(featuresDictLock);
4569 	}
4570 
4571 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4572 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4573 	OSSharedPtr<OSDictionary> features;
4574 
4575 	// Create new features dict if necessary
4576 	if (origFeatures) {
4577 		features = OSDictionary::withDictionary(origFeatures);
4578 	} else {
4579 		features = OSDictionary::withCapacity(1);
4580 	}
4581 
4582 	// Create OSNumber to track new feature
4583 
4584 	next_feature_id += 1;
4585 	if (uniqueFeatureID) {
4586 		// We don't really mind if the calling kext didn't give us a place
4587 		// to stash their unique id. Many kexts don't plan to unload, and thus
4588 		// have no need to remove themselves later.
4589 		*uniqueFeatureID = next_feature_id;
4590 	}
4591 
4592 	feature_value = (uint32_t)next_feature_id;
4593 	feature_value <<= 16;
4594 	feature_value += supportedWhere;
4595 
4596 	new_feature_data = OSNumber::withNumber(
4597 		(unsigned long long)feature_value, 32);
4598 
4599 	// Does features object already exist?
4600 	if ((osObj = features->getObject(feature))) {
4601 		if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4602 			// We need to create an OSArray to hold the now 2 elements.
4603 			existing_feature_arr = OSArray::withObjects(
4604 				(const OSObject **)&existing_feature, 1, 2);
4605 		} else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4606 			// Add object to existing array
4607 			existing_feature_arr = OSArray::withArray(
4608 				existing_feature_arr_raw,
4609 				existing_feature_arr_raw->getCount() + 1);
4610 		}
4611 
4612 		if (existing_feature_arr) {
4613 			existing_feature_arr->setObject(new_feature_data.get());
4614 			features->setObject(feature, existing_feature_arr.get());
4615 		}
4616 	} else {
4617 		// The easy case: no previously existing features listed. We simply
4618 		// set the OSNumber at key 'feature' and we're on our way.
4619 		features->setObject(feature, new_feature_data.get());
4620 	}
4621 
4622 	setProperty(kRootDomainSupportedFeatures, features.get());
4623 
4624 	if (featuresDictLock) {
4625 		IOLockUnlock(featuresDictLock);
4626 	}
4627 
4628 	// Notify EnergySaver and all those in user space so they might
4629 	// re-populate their feature specific UI
4630 	if (pmPowerStateQueue) {
4631 		pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4632 	}
4633 }
4634 
4635 //******************************************************************************
4636 // removePublishedFeature
4637 //
4638 // Removes previously published feature
4639 //******************************************************************************
4640 
4641 IOReturn
4642 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4643 {
4644 	IOReturn                ret = kIOReturnError;
4645 	uint32_t                feature_value = 0;
4646 	uint16_t                feature_id = 0;
4647 	bool                    madeAChange = false;
4648 
4649 	OSSymbol                *dictKey = NULL;
4650 	OSSharedPtr<OSCollectionIterator>    dictIterator;
4651 	OSArray                 *arrayMember  = NULL;
4652 	OSNumber                *numberMember = NULL;
4653 	OSObject                *osObj        = NULL;
4654 	OSNumber                *osNum        = NULL;
4655 	OSSharedPtr<OSArray>    arrayMemberCopy;
4656 
4657 	if (kBadPMFeatureID == removeFeatureID) {
4658 		return kIOReturnNotFound;
4659 	}
4660 
4661 	if (featuresDictLock) {
4662 		IOLockLock(featuresDictLock);
4663 	}
4664 
4665 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4666 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4667 	OSSharedPtr<OSDictionary> features;
4668 
4669 	if (origFeatures) {
4670 		// Any modifications to the dictionary are made to the copy to prevent
4671 		// races & crashes with userland clients. Dictionary updated
4672 		// automically later.
4673 		features = OSDictionary::withDictionary(origFeatures);
4674 	} else {
4675 		features = NULL;
4676 		ret = kIOReturnNotFound;
4677 		goto exit;
4678 	}
4679 
4680 	// We iterate 'features' dictionary looking for an entry tagged
4681 	// with 'removeFeatureID'. If found, we remove it from our tracking
4682 	// structures and notify the OS via a general interest message.
4683 
4684 	dictIterator = OSCollectionIterator::withCollection(features.get());
4685 	if (!dictIterator) {
4686 		goto exit;
4687 	}
4688 
4689 	while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4690 		osObj = features->getObject(dictKey);
4691 
4692 		// Each Feature is either tracked by an OSNumber
4693 		if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4694 			feature_value = numberMember->unsigned32BitValue();
4695 			feature_id = (uint16_t)(feature_value >> 16);
4696 
4697 			if (feature_id == (uint16_t)removeFeatureID) {
4698 				// Remove this node
4699 				features->removeObject(dictKey);
4700 				madeAChange = true;
4701 				break;
4702 			}
4703 
4704 			// Or tracked by an OSArray of OSNumbers
4705 		} else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4706 			unsigned int arrayCount = arrayMember->getCount();
4707 
4708 			for (unsigned int i = 0; i < arrayCount; i++) {
4709 				osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4710 				if (!osNum) {
4711 					continue;
4712 				}
4713 
4714 				feature_value = osNum->unsigned32BitValue();
4715 				feature_id = (uint16_t)(feature_value >> 16);
4716 
4717 				if (feature_id == (uint16_t)removeFeatureID) {
4718 					// Remove this node
4719 					if (1 == arrayCount) {
4720 						// If the array only contains one element, remove
4721 						// the whole thing.
4722 						features->removeObject(dictKey);
4723 					} else {
4724 						// Otherwise remove the element from a copy of the array.
4725 						arrayMemberCopy = OSArray::withArray(arrayMember);
4726 						if (arrayMemberCopy) {
4727 							arrayMemberCopy->removeObject(i);
4728 							features->setObject(dictKey, arrayMemberCopy.get());
4729 						}
4730 					}
4731 
4732 					madeAChange = true;
4733 					break;
4734 				}
4735 			}
4736 		}
4737 	}
4738 
4739 	if (madeAChange) {
4740 		ret = kIOReturnSuccess;
4741 
4742 		setProperty(kRootDomainSupportedFeatures, features.get());
4743 
4744 		// Notify EnergySaver and all those in user space so they might
4745 		// re-populate their feature specific UI
4746 		if (pmPowerStateQueue) {
4747 			pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4748 		}
4749 	} else {
4750 		ret = kIOReturnNotFound;
4751 	}
4752 
4753 exit:
4754 	if (featuresDictLock) {
4755 		IOLockUnlock(featuresDictLock);
4756 	}
4757 	return ret;
4758 }
4759 
4760 //******************************************************************************
4761 // publishPMSetting (private)
4762 //
4763 // Should only be called by PMSettingObject to publish a PM Setting as a
4764 // supported feature.
4765 //******************************************************************************
4766 
4767 void
4768 IOPMrootDomain::publishPMSetting(
4769 	const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4770 {
4771 	if (noPublishPMSettings &&
4772 	    (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4773 		// Setting found in noPublishPMSettings array
4774 		*featureID = kBadPMFeatureID;
4775 		return;
4776 	}
4777 
4778 	publishFeature(
4779 		feature->getCStringNoCopy(), where, featureID);
4780 }
4781 
4782 //******************************************************************************
4783 // setPMSetting (private)
4784 //
4785 // Internal helper to relay PM settings changes from user space to individual
4786 // drivers. Should be called only by IOPMrootDomain::setProperties.
4787 //******************************************************************************
4788 
4789 IOReturn
4790 IOPMrootDomain::setPMSetting(
4791 	const OSSymbol  *type,
4792 	OSObject        *object )
4793 {
4794 	PMSettingCallEntry  *entries = NULL;
4795 	OSSharedPtr<OSArray>    chosen;
4796 	const OSArray       *array;
4797 	PMSettingObject     *pmso;
4798 	thread_t            thisThread;
4799 	int                 i, j, count, capacity;
4800 	bool                ok = false;
4801 	IOReturn            ret;
4802 
4803 	if (NULL == type) {
4804 		return kIOReturnBadArgument;
4805 	}
4806 
4807 	PMSETTING_LOCK();
4808 
4809 	// Update settings dict so changes are visible from copyPMSetting().
4810 	fPMSettingsDict->setObject(type, object);
4811 
4812 	// Prep all PMSetting objects with the given 'type' for callout.
4813 	array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4814 	if (!array || ((capacity = array->getCount()) == 0)) {
4815 		goto unlock_exit;
4816 	}
4817 
4818 	// Array to retain PMSetting objects targeted for callout.
4819 	chosen = OSArray::withCapacity(capacity);
4820 	if (!chosen) {
4821 		goto unlock_exit; // error
4822 	}
4823 	entries = IONew(PMSettingCallEntry, capacity);
4824 	if (!entries) {
4825 		goto unlock_exit; // error
4826 	}
4827 	memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4828 
4829 	thisThread = current_thread();
4830 
4831 	for (i = 0, j = 0; i < capacity; i++) {
4832 		pmso = (PMSettingObject *) array->getObject(i);
4833 		if (pmso->disabled) {
4834 			continue;
4835 		}
4836 		entries[j].thread = thisThread;
4837 		queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4838 		chosen->setObject(pmso);
4839 		j++;
4840 	}
4841 	count = j;
4842 	if (!count) {
4843 		goto unlock_exit;
4844 	}
4845 
4846 	PMSETTING_UNLOCK();
4847 
4848 	// Call each pmso in the chosen array.
4849 	for (i = 0; i < count; i++) {
4850 		pmso = (PMSettingObject *) chosen->getObject(i);
4851 		ret = pmso->dispatchPMSetting(type, object);
4852 		if (ret == kIOReturnSuccess) {
4853 			// At least one setting handler was successful
4854 			ok = true;
4855 #if DEVELOPMENT || DEBUG
4856 		} else {
4857 			// Log the handler and kext that failed
4858 			OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4859 			if (kextName) {
4860 				DLOG("PMSetting(%s) error 0x%x from %s\n",
4861 				    type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4862 			}
4863 #endif
4864 		}
4865 	}
4866 
4867 	PMSETTING_LOCK();
4868 	for (i = 0; i < count; i++) {
4869 		pmso = (PMSettingObject *) chosen->getObject(i);
4870 		queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4871 		if (pmso->waitThread) {
4872 			PMSETTING_WAKEUP(pmso);
4873 		}
4874 	}
4875 
4876 	if (ok) {
4877 		recordRTCAlarm(type, object);
4878 	}
4879 unlock_exit:
4880 	PMSETTING_UNLOCK();
4881 
4882 	if (entries) {
4883 		IODelete(entries, PMSettingCallEntry, capacity);
4884 	}
4885 
4886 	return kIOReturnSuccess;
4887 }
4888 
4889 //******************************************************************************
4890 // copyPMSetting (public)
4891 //
4892 // Allows kexts to safely read setting values, without being subscribed to
4893 // notifications.
4894 //******************************************************************************
4895 
4896 OSSharedPtr<OSObject>
4897 IOPMrootDomain::copyPMSetting(
4898 	OSSymbol *whichSetting)
4899 {
4900 	OSSharedPtr<OSObject> obj;
4901 
4902 	if (!whichSetting) {
4903 		return NULL;
4904 	}
4905 
4906 	PMSETTING_LOCK();
4907 	obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4908 	PMSETTING_UNLOCK();
4909 
4910 	return obj;
4911 }
4912 
4913 //******************************************************************************
4914 // registerPMSettingController (public)
4915 //
4916 // direct wrapper to registerPMSettingController with uint32_t power source arg
4917 //******************************************************************************
4918 
4919 IOReturn
4920 IOPMrootDomain::registerPMSettingController(
4921 	const OSSymbol *                settings[],
4922 	IOPMSettingControllerCallback   func,
4923 	OSObject                        *target,
4924 	uintptr_t                       refcon,
4925 	OSObject                        **handle)
4926 {
4927 	return registerPMSettingController(
4928 		settings,
4929 		(kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4930 		func, target, refcon, handle);
4931 }
4932 
4933 //******************************************************************************
4934 // registerPMSettingController (public)
4935 //
4936 // Kexts may register for notifications when a particular setting is changed.
4937 // A list of settings is available in IOPM.h.
4938 // Arguments:
4939 //  * settings - An OSArray containing OSSymbols. Caller should populate this
4940 //          array with a list of settings caller wants notifications from.
4941 //  * func - A C function callback of the type IOPMSettingControllerCallback
4942 //  * target - caller may provide an OSObject *, which PM will pass as an
4943 //          target to calls to "func"
4944 //  * refcon - caller may provide an void *, which PM will pass as an
4945 //          argument to calls to "func"
4946 //  * handle - This is a return argument. We will populate this pointer upon
4947 //          call success. Hold onto this and pass this argument to
4948 //          IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4949 // Returns:
4950 //      kIOReturnSuccess on success
4951 //******************************************************************************
4952 
4953 IOReturn
4954 IOPMrootDomain::registerPMSettingController(
4955 	const OSSymbol *                settings[],
4956 	uint32_t                        supportedPowerSources,
4957 	IOPMSettingControllerCallback   func,
4958 	OSObject                        *target,
4959 	uintptr_t                       refcon,
4960 	OSObject                        **handle)
4961 {
4962 	PMSettingObject *pmso = NULL;
4963 	OSObject        *pmsh = NULL;
4964 	int             i;
4965 
4966 	if (NULL == settings ||
4967 	    NULL == func ||
4968 	    NULL == handle) {
4969 		return kIOReturnBadArgument;
4970 	}
4971 
4972 	pmso = PMSettingObject::pmSettingObject(
4973 		(IOPMrootDomain *) this, func, target,
4974 		refcon, supportedPowerSources, settings, &pmsh);
4975 
4976 	if (!pmso) {
4977 		*handle = NULL;
4978 		return kIOReturnInternalError;
4979 	}
4980 
4981 	PMSETTING_LOCK();
4982 	for (i = 0; settings[i]; i++) {
4983 		OSSharedPtr<OSArray> newList;
4984 		OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4985 		if (!list) {
4986 			// New array of callbacks for this setting
4987 			newList = OSArray::withCapacity(1);
4988 			settingsCallbacks->setObject(settings[i], newList.get());
4989 			list = newList.get();
4990 		}
4991 
4992 		// Add caller to the callback list
4993 		list->setObject(pmso);
4994 	}
4995 	PMSETTING_UNLOCK();
4996 
4997 	// Return handle to the caller, the setting object is private.
4998 	*handle = pmsh;
4999 
5000 	return kIOReturnSuccess;
5001 }
5002 
5003 //******************************************************************************
5004 // deregisterPMSettingObject (private)
5005 //
5006 // Only called from PMSettingObject.
5007 //******************************************************************************
5008 
5009 void
5010 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
5011 {
5012 	thread_t                thisThread = current_thread();
5013 	PMSettingCallEntry      *callEntry;
5014 	OSSharedPtr<OSCollectionIterator>    iter;
5015 	OSSymbol                *sym;
5016 	OSArray                 *array;
5017 	int                     index;
5018 	bool                    wait;
5019 
5020 	PMSETTING_LOCK();
5021 
5022 	pmso->disabled = true;
5023 
5024 	// Wait for all callout threads to finish.
5025 	do {
5026 		wait = false;
5027 		queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5028 		{
5029 			if (callEntry->thread != thisThread) {
5030 				wait = true;
5031 				break;
5032 			}
5033 		}
5034 		if (wait) {
5035 			assert(NULL == pmso->waitThread);
5036 			pmso->waitThread = thisThread;
5037 			PMSETTING_WAIT(pmso);
5038 			pmso->waitThread = NULL;
5039 		}
5040 	} while (wait);
5041 
5042 	// Search each PM settings array in the kernel.
5043 	iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5044 	if (iter) {
5045 		while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5046 			array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5047 			index = array->getNextIndexOfObject(pmso, 0);
5048 			if (-1 != index) {
5049 				array->removeObject(index);
5050 			}
5051 		}
5052 	}
5053 
5054 	PMSETTING_UNLOCK();
5055 
5056 	pmso->release();
5057 }
5058 
5059 //******************************************************************************
5060 // informCPUStateChange
5061 //
5062 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5063 // running on battery, with the lid closed, etc.
5064 //
5065 // informCPUStateChange is a no-op on non x86 systems
5066 // only x86 has explicit support in the IntelCPUPowerManagement kext
5067 //******************************************************************************
5068 
5069 void
5070 IOPMrootDomain::informCPUStateChange(
5071 	uint32_t type,
5072 	uint32_t value )
5073 {
5074 #if defined(__i386__) || defined(__x86_64__)
5075 
5076 	pmioctlVariableInfo_t varInfoStruct;
5077 	int                 pmCPUret = 0;
5078 	const char          *varNameStr = NULL;
5079 	int32_t             *varIndex   = NULL;
5080 
5081 	if (kInformAC == type) {
5082 		varNameStr = kIOPMRootDomainBatPowerCString;
5083 		varIndex = &idxPMCPULimitedPower;
5084 	} else if (kInformLid == type) {
5085 		varNameStr = kIOPMRootDomainLidCloseCString;
5086 		varIndex = &idxPMCPUClamshell;
5087 	} else {
5088 		return;
5089 	}
5090 
5091 	// Set the new value!
5092 	// pmCPUControl will assign us a new ID if one doesn't exist yet
5093 	bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5094 	varInfoStruct.varID         = *varIndex;
5095 	varInfoStruct.varType       = vBool;
5096 	varInfoStruct.varInitValue  = value;
5097 	varInfoStruct.varCurValue   = value;
5098 	strlcpy((char *)varInfoStruct.varName,
5099 	    (const char *)varNameStr,
5100 	    sizeof(varInfoStruct.varName));
5101 
5102 	// Set!
5103 	pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5104 
5105 	// pmCPU only assigns numerical id's when a new varName is specified
5106 	if ((0 == pmCPUret)
5107 	    && (*varIndex == kCPUUnknownIndex)) {
5108 		// pmCPUControl has assigned us a new variable ID.
5109 		// Let's re-read the structure we just SET to learn that ID.
5110 		pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5111 
5112 		if (0 == pmCPUret) {
5113 			// Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5114 			*varIndex = varInfoStruct.varID;
5115 		}
5116 	}
5117 
5118 	return;
5119 
5120 #endif /* __i386__ || __x86_64__ */
5121 }
5122 
5123 // MARK: -
5124 // MARK: Deep Sleep Policy
5125 
5126 #if HIBERNATION
5127 
5128 //******************************************************************************
5129 // evaluateSystemSleepPolicy
5130 //******************************************************************************
5131 
5132 #define kIOPlatformSystemSleepPolicyKey     "IOPlatformSystemSleepPolicy"
5133 
5134 // Sleep flags
5135 enum {
5136 	kIOPMSleepFlagHibernate         = 0x00000001,
5137 	kIOPMSleepFlagSleepTimerEnable  = 0x00000002
5138 };
5139 
5140 struct IOPMSystemSleepPolicyEntry {
5141 	uint32_t    factorMask;
5142 	uint32_t    factorBits;
5143 	uint32_t    sleepFlags;
5144 	uint32_t    wakeEvents;
5145 } __attribute__((packed));
5146 
5147 struct IOPMSystemSleepPolicyTable {
5148 	uint32_t    signature;
5149 	uint16_t    version;
5150 	uint16_t    entryCount;
5151 	IOPMSystemSleepPolicyEntry  entries[];
5152 } __attribute__((packed));
5153 
5154 enum {
5155 	kIOPMSleepAttributeHibernateSetup   = 0x00000001,
5156 	kIOPMSleepAttributeHibernateSleep   = 0x00000002
5157 };
5158 
5159 static uint32_t
5160 getSleepTypeAttributes( uint32_t sleepType )
5161 {
5162 	static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5163 	{
5164 		/* invalid   */ 0,
5165 		/* abort     */ 0,
5166 		/* normal    */ 0,
5167 		/* safesleep */ kIOPMSleepAttributeHibernateSetup,
5168 		/* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5169 		/* standby   */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5170 		/* poweroff  */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5171 		/* deepidle  */ 0
5172 	};
5173 
5174 	if (sleepType >= kIOPMSleepTypeLast) {
5175 		return 0;
5176 	}
5177 
5178 	return sleepTypeAttributes[sleepType];
5179 }
5180 
5181 bool
5182 IOPMrootDomain::evaluateSystemSleepPolicy(
5183 	IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5184 {
5185 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5186 
5187 	static const IONamedValue factorValues[] = {
5188 		SLEEP_FACTOR( SleepTimerWake ),
5189 		SLEEP_FACTOR( LidOpen ),
5190 		SLEEP_FACTOR( ACPower ),
5191 		SLEEP_FACTOR( BatteryLow ),
5192 		SLEEP_FACTOR( StandbyNoDelay ),
5193 		SLEEP_FACTOR( StandbyForced ),
5194 		SLEEP_FACTOR( StandbyDisabled ),
5195 		SLEEP_FACTOR( USBExternalDevice ),
5196 		SLEEP_FACTOR( BluetoothHIDDevice ),
5197 		SLEEP_FACTOR( ExternalMediaMounted ),
5198 		SLEEP_FACTOR( ThunderboltDevice ),
5199 		SLEEP_FACTOR( RTCAlarmScheduled ),
5200 		SLEEP_FACTOR( MagicPacketWakeEnabled ),
5201 		SLEEP_FACTOR( HibernateForced ),
5202 		SLEEP_FACTOR( AutoPowerOffDisabled ),
5203 		SLEEP_FACTOR( AutoPowerOffForced ),
5204 		SLEEP_FACTOR( ExternalDisplay ),
5205 		SLEEP_FACTOR( NetworkKeepAliveActive ),
5206 		SLEEP_FACTOR( LocalUserActivity ),
5207 		SLEEP_FACTOR( HibernateFailed ),
5208 		SLEEP_FACTOR( ThermalWarning ),
5209 		SLEEP_FACTOR( DisplayCaptured ),
5210 		{ 0, NULL }
5211 	};
5212 
5213 	const IOPMSystemSleepPolicyTable * pt;
5214 	OSSharedPtr<OSObject>  prop;
5215 	OSData *    policyData;
5216 	uint64_t    currentFactors = 0;
5217 	char        currentFactorsBuf[512];
5218 	uint32_t    standbyDelay   = 0;
5219 	uint32_t    powerOffDelay  = 0;
5220 	uint32_t    powerOffTimer  = 0;
5221 	uint32_t    standbyTimer  = 0;
5222 	uint32_t    mismatch;
5223 	bool        standbyEnabled;
5224 	bool        powerOffEnabled;
5225 	bool        found = false;
5226 
5227 	// Get platform's sleep policy table
5228 	if (!gSleepPolicyHandler) {
5229 		prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5230 		if (!prop) {
5231 			goto done;
5232 		}
5233 	}
5234 
5235 	// Fetch additional settings
5236 	standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5237 	    && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5238 	powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5239 	    && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5240 	if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5241 		powerOffTimer = powerOffDelay;
5242 	}
5243 	if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5244 		standbyTimer = standbyDelay;
5245 	}
5246 
5247 	DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5248 	    sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5249 	    powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5250 
5251 	currentFactorsBuf[0] = 0;
5252 	// pmset level overrides
5253 	if ((*hibMode & kIOHibernateModeOn) == 0) {
5254 		if (!gSleepPolicyHandler) {
5255 			standbyEnabled  = false;
5256 			powerOffEnabled = false;
5257 		}
5258 	} else if (!(*hibMode & kIOHibernateModeSleep)) {
5259 		// Force hibernate (i.e. mode 25)
5260 		// If standby is enabled, force standy.
5261 		// If poweroff is enabled, force poweroff.
5262 		if (standbyEnabled) {
5263 			currentFactors |= kIOPMSleepFactorStandbyForced;
5264 		} else if (powerOffEnabled) {
5265 			currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5266 		} else {
5267 			currentFactors |= kIOPMSleepFactorHibernateForced;
5268 		}
5269 	}
5270 
5271 	// Current factors based on environment and assertions
5272 	if (sleepTimerMaintenance) {
5273 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5274 	}
5275 	if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5276 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5277 	}
5278 	if (!clamshellClosed) {
5279 		currentFactors |= kIOPMSleepFactorLidOpen;
5280 	}
5281 	if (acAdaptorConnected) {
5282 		currentFactors |= kIOPMSleepFactorACPower;
5283 	}
5284 	if (lowBatteryCondition) {
5285 		hibernateMode = 0;
5286 		getSleepOption(kIOHibernateModeKey, &hibernateMode);
5287 		if ((hibernateMode & kIOHibernateModeOn) == 0) {
5288 			DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5289 		} else {
5290 			currentFactors |= kIOPMSleepFactorBatteryLow;
5291 		}
5292 	}
5293 	if (!standbyDelay || !standbyTimer) {
5294 		currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5295 	}
5296 	if (standbyNixed || !standbyEnabled) {
5297 		currentFactors |= kIOPMSleepFactorStandbyDisabled;
5298 	}
5299 	if (resetTimers) {
5300 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5301 		currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5302 	}
5303 	if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5304 	    kIOPMDriverAssertionLevelOff) {
5305 		currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5306 	}
5307 	if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5308 	    kIOPMDriverAssertionLevelOff) {
5309 		currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5310 	}
5311 	if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5312 	    kIOPMDriverAssertionLevelOff) {
5313 		currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5314 	}
5315 	if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5316 	    kIOPMDriverAssertionLevelOff) {
5317 		currentFactors |= kIOPMSleepFactorThunderboltDevice;
5318 	}
5319 	if (_scheduledAlarmMask != 0) {
5320 		currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5321 	}
5322 	if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5323 	    kIOPMDriverAssertionLevelOff) {
5324 		currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5325 	}
5326 #define TCPKEEPALIVE 1
5327 #if TCPKEEPALIVE
5328 	if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5329 	    kIOPMDriverAssertionLevelOff) {
5330 		currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5331 	}
5332 #endif
5333 	if (!powerOffEnabled) {
5334 		currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5335 	}
5336 	if (desktopMode) {
5337 		currentFactors |= kIOPMSleepFactorExternalDisplay;
5338 	}
5339 	if (userWasActive) {
5340 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5341 	}
5342 	if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5343 		currentFactors |= kIOPMSleepFactorHibernateFailed;
5344 	}
5345 	if (thermalWarningState) {
5346 		currentFactors |= kIOPMSleepFactorThermalWarning;
5347 	}
5348 
5349 	for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5350 		uint32_t factor = 1 << factorBit;
5351 		if (factor & currentFactors) {
5352 			strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5353 			strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5354 		}
5355 	}
5356 	DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5357 
5358 	if (gSleepPolicyHandler) {
5359 		uint32_t    savedHibernateMode;
5360 		IOReturn    result;
5361 
5362 		if (!gSleepPolicyVars) {
5363 			gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5364 		}
5365 		gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5366 		gSleepPolicyVars->version   = kIOPMSystemSleepPolicyVersion;
5367 		gSleepPolicyVars->currentCapability = _currentCapability;
5368 		gSleepPolicyVars->highestCapability = _highestCapability;
5369 		gSleepPolicyVars->sleepFactors      = currentFactors;
5370 		gSleepPolicyVars->sleepReason       = lastSleepReason;
5371 		gSleepPolicyVars->sleepPhase        = sleepPhase;
5372 		gSleepPolicyVars->standbyDelay      = standbyDelay;
5373 		gSleepPolicyVars->standbyTimer      = standbyTimer;
5374 		gSleepPolicyVars->poweroffDelay     = powerOffDelay;
5375 		gSleepPolicyVars->scheduledAlarms   = _scheduledAlarmMask | _userScheduledAlarmMask;
5376 		gSleepPolicyVars->poweroffTimer     = powerOffTimer;
5377 
5378 		if (kIOPMSleepPhase0 == sleepPhase) {
5379 			// preserve hibernateMode
5380 			savedHibernateMode = gSleepPolicyVars->hibernateMode;
5381 			gSleepPolicyVars->hibernateMode = *hibMode;
5382 		} else if (kIOPMSleepPhase1 == sleepPhase) {
5383 			// use original hibernateMode for phase2
5384 			gSleepPolicyVars->hibernateMode = *hibMode;
5385 		}
5386 
5387 		result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5388 
5389 		if (kIOPMSleepPhase0 == sleepPhase) {
5390 			// restore hibernateMode
5391 			gSleepPolicyVars->hibernateMode = savedHibernateMode;
5392 		}
5393 
5394 		if ((result != kIOReturnSuccess) ||
5395 		    (kIOPMSleepTypeInvalid == params->sleepType) ||
5396 		    (params->sleepType >= kIOPMSleepTypeLast) ||
5397 		    (kIOPMSystemSleepParametersVersion != params->version)) {
5398 			MSG("sleep policy handler error\n");
5399 			goto done;
5400 		}
5401 
5402 		if ((getSleepTypeAttributes(params->sleepType) &
5403 		    kIOPMSleepAttributeHibernateSetup) &&
5404 		    ((*hibMode & kIOHibernateModeOn) == 0)) {
5405 			*hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5406 		}
5407 
5408 		DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5409 		    params->version, params->sleepType, params->sleepFlags,
5410 		    params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5411 		found = true;
5412 		goto done;
5413 	}
5414 
5415 	// Policy table is meaningless without standby enabled
5416 	if (!standbyEnabled) {
5417 		goto done;
5418 	}
5419 
5420 	// Validate the sleep policy table
5421 	policyData = OSDynamicCast(OSData, prop.get());
5422 	if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5423 		goto done;
5424 	}
5425 
5426 	pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5427 	if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5428 	    (pt->version != 1) || (0 == pt->entryCount)) {
5429 		goto done;
5430 	}
5431 
5432 	if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5433 	    (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5434 		goto done;
5435 	}
5436 
5437 	for (uint32_t i = 0; i < pt->entryCount; i++) {
5438 		const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5439 		mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5440 
5441 		DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5442 		    entry->factorMask, entry->factorBits,
5443 		    entry->sleepFlags, entry->wakeEvents, mismatch);
5444 		if (mismatch) {
5445 			continue;
5446 		}
5447 
5448 		DLOG("^ found match\n");
5449 		found = true;
5450 
5451 		params->version = kIOPMSystemSleepParametersVersion;
5452 		params->reserved1 = 1;
5453 		if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5454 			params->sleepType = kIOPMSleepTypeStandby;
5455 		} else {
5456 			params->sleepType = kIOPMSleepTypeNormalSleep;
5457 		}
5458 
5459 		params->ecWakeEvents = entry->wakeEvents;
5460 		if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5461 			if (kIOPMSleepPhase2 == sleepPhase) {
5462 				clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5463 
5464 				if (!_standbyTimerResetSeconds ||
5465 				    (now_secs <= _standbyTimerResetSeconds)) {
5466 					// Reset standby timer adjustment
5467 					_standbyTimerResetSeconds = now_secs;
5468 					DLOG("standby delay %u, reset %u\n",
5469 					    standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5470 				} else if (standbyDelay) {
5471 					// Shorten the standby delay timer
5472 					clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5473 					if (standbyDelay > elapsed) {
5474 						standbyDelay -= elapsed;
5475 					} else {
5476 						standbyDelay = 1; // must be > 0
5477 					}
5478 					DLOG("standby delay %u, elapsed %u\n",
5479 					    standbyDelay, (uint32_t) elapsed);
5480 				}
5481 			}
5482 			params->ecWakeTimer = standbyDelay;
5483 		} else if (kIOPMSleepPhase2 == sleepPhase) {
5484 			// A sleep that does not enable the sleep timer will reset
5485 			// the standby delay adjustment.
5486 			_standbyTimerResetSeconds = 0;
5487 		}
5488 		break;
5489 	}
5490 
5491 done:
5492 	return found;
5493 }
5494 
5495 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5496 
5497 void
5498 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5499 {
5500 	// Evaluate early (priority interest phase), before drivers sleep.
5501 
5502 	DLOG("%s\n", __FUNCTION__);
5503 	removeProperty(kIOPMSystemSleepParametersKey);
5504 
5505 	// Full wake resets the standby timer delay adjustment
5506 	if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5507 		_standbyTimerResetSeconds = 0;
5508 	}
5509 
5510 	hibernateDisabled = false;
5511 	hibernateMode = 0;
5512 	getSleepOption(kIOHibernateModeKey, &hibernateMode);
5513 
5514 	// Save for late evaluation if sleep is aborted
5515 	bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5516 
5517 	if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5518 	    &hibernateMode)) {
5519 		if (!hibernateRetry &&
5520 		    ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5521 		    kIOPMSleepAttributeHibernateSetup) == 0)) {
5522 			// skip hibernate setup
5523 			hibernateDisabled = true;
5524 		}
5525 	}
5526 
5527 	// Publish IOPMSystemSleepType
5528 	uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5529 	if (sleepType == kIOPMSleepTypeInvalid) {
5530 		// no sleep policy
5531 		sleepType = kIOPMSleepTypeNormalSleep;
5532 		if (hibernateMode & kIOHibernateModeOn) {
5533 			sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5534 			    kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5535 		}
5536 	} else if ((sleepType == kIOPMSleepTypeStandby) &&
5537 	    (gEarlySystemSleepParams.ecPoweroffTimer)) {
5538 		// report the lowest possible sleep state
5539 		sleepType = kIOPMSleepTypePowerOff;
5540 	}
5541 
5542 	setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5543 }
5544 
5545 void
5546 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5547 {
5548 	IOPMSystemSleepParameters   params;
5549 	OSSharedPtr<OSData>         paramsData;
5550 	bool                        wakeNow;
5551 	// Evaluate sleep policy after sleeping drivers but before platform sleep.
5552 
5553 	DLOG("%s\n", __FUNCTION__);
5554 
5555 	bzero(&params, sizeof(params));
5556 	wakeNow = false;
5557 	if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
5558 		if ((kIOPMSleepTypeStandby == params.sleepType)
5559 		    && gIOHibernateStandbyDisabled && gSleepPolicyVars
5560 		    && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5561 		    & gSleepPolicyVars->sleepFactors))) {
5562 			standbyNixed = true;
5563 			wakeNow = true;
5564 		}
5565 		if (wakeNow
5566 		    || ((hibernateDisabled || hibernateAborted) &&
5567 		    (getSleepTypeAttributes(params.sleepType) &
5568 		    kIOPMSleepAttributeHibernateSetup))) {
5569 			// Final evaluation picked a state requiring hibernation,
5570 			// but hibernate isn't going to proceed. Arm a short sleep using
5571 			// the early non-hibernate sleep parameters.
5572 			bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
5573 			params.sleepType = kIOPMSleepTypeAbortedSleep;
5574 			params.ecWakeTimer = 1;
5575 			if (standbyNixed) {
5576 				resetTimers = true;
5577 			} else {
5578 				// Set hibernateRetry flag to force hibernate setup on the
5579 				// next sleep.
5580 				hibernateRetry = true;
5581 			}
5582 			DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5583 			    params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5584 		} else {
5585 			hibernateRetry = false;
5586 		}
5587 
5588 		if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5589 			resetTimers = false;
5590 		}
5591 
5592 		paramsData = OSData::withValue(params);
5593 		if (paramsData) {
5594 			setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5595 		}
5596 
5597 		if (getSleepTypeAttributes(params.sleepType) &
5598 		    kIOPMSleepAttributeHibernateSleep) {
5599 			// Disable sleep to force hibernation
5600 			gIOHibernateMode &= ~kIOHibernateModeSleep;
5601 		}
5602 	}
5603 }
5604 
5605 bool
5606 IOPMrootDomain::getHibernateSettings(
5607 	uint32_t *  hibernateModePtr,
5608 	uint32_t *  hibernateFreeRatio,
5609 	uint32_t *  hibernateFreeTime )
5610 {
5611 	// Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5612 	// has updated the hibernateDisabled flag.
5613 
5614 	bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5615 	getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5616 	getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5617 	if (hibernateDisabled) {
5618 		*hibernateModePtr = 0;
5619 	} else if (gSleepPolicyHandler) {
5620 		*hibernateModePtr = hibernateMode;
5621 	}
5622 	DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5623 	return ok;
5624 }
5625 
5626 bool
5627 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5628 {
5629 	OSSharedPtr<OSObject>       optionsProp;
5630 	OSDictionary *              optionsDict;
5631 	OSSharedPtr<OSObject>       obj;
5632 	OSNumber *                  num;
5633 	bool                        ok = false;
5634 
5635 	optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5636 	optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5637 
5638 	if (optionsDict) {
5639 		obj.reset(optionsDict->getObject(key), OSRetain);
5640 	}
5641 	if (!obj) {
5642 		obj = copyProperty(key);
5643 	}
5644 	if (obj) {
5645 		if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5646 			*option = num->unsigned32BitValue();
5647 			ok = true;
5648 		} else if (OSDynamicCast(OSBoolean, obj.get())) {
5649 			*option = (obj == kOSBooleanTrue) ? 1 : 0;
5650 			ok = true;
5651 		}
5652 	}
5653 
5654 	return ok;
5655 }
5656 #endif /* HIBERNATION */
5657 
5658 IOReturn
5659 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5660 {
5661 #if HIBERNATION
5662 	IOPMSystemSleepParameters   params;
5663 	uint32_t                    hibMode = 0;
5664 	bool                        ok;
5665 
5666 	if (gIOPMWorkLoop->inGate() == false) {
5667 		IOReturn ret = gIOPMWorkLoop->runAction(
5668 			OSMemberFunctionCast(IOWorkLoop::Action, this,
5669 			&IOPMrootDomain::getSystemSleepType),
5670 			(OSObject *) this,
5671 			(void *) sleepType, (void *) standbyTimer);
5672 		return ret;
5673 	}
5674 
5675 	getSleepOption(kIOHibernateModeKey, &hibMode);
5676 	bzero(&params, sizeof(params));
5677 
5678 	ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
5679 	if (ok) {
5680 		*sleepType = params.sleepType;
5681 		if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5682 		    !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5683 			DLOG("Standby delay is not set\n");
5684 			*standbyTimer = 0;
5685 		}
5686 		return kIOReturnSuccess;
5687 	}
5688 #endif
5689 
5690 	return kIOReturnUnsupported;
5691 }
5692 
5693 // MARK: -
5694 // MARK: Shutdown and Restart
5695 
5696 //******************************************************************************
5697 // handlePlatformHaltRestart
5698 //
5699 //******************************************************************************
5700 
5701 // Phases while performing shutdown/restart
5702 typedef enum {
5703 	kNotifyDone                 = 0x00,
5704 	kNotifyPriorityClients      = 0x10,
5705 	kNotifyPowerPlaneDrivers    = 0x20,
5706 	kNotifyHaltRestartAction    = 0x30,
5707 	kQuiescePM                  = 0x40,
5708 } shutdownPhase_t;
5709 
5710 
5711 struct HaltRestartApplierContext {
5712 	IOPMrootDomain *    RootDomain;
5713 	unsigned long       PowerState;
5714 	IOPMPowerFlags      PowerFlags;
5715 	UInt32              MessageType;
5716 	UInt32              Counter;
5717 	const char *        LogString;
5718 	shutdownPhase_t     phase;
5719 
5720 	IOServiceInterestHandler    handler;
5721 } gHaltRestartCtx;
5722 
5723 const char *
5724 shutdownPhase2String(shutdownPhase_t phase)
5725 {
5726 	switch (phase) {
5727 	case kNotifyDone:
5728 		return "Notifications completed";
5729 	case kNotifyPriorityClients:
5730 		return "Notifying priority clients";
5731 	case kNotifyPowerPlaneDrivers:
5732 		return "Notifying power plane drivers";
5733 	case kNotifyHaltRestartAction:
5734 		return "Notifying HaltRestart action handlers";
5735 	case kQuiescePM:
5736 		return "Quiescing PM";
5737 	default:
5738 		return "Unknown";
5739 	}
5740 }
5741 
5742 static void
5743 platformHaltRestartApplier( OSObject * object, void * context )
5744 {
5745 	IOPowerStateChangeNotification  notify;
5746 	HaltRestartApplierContext *     ctx;
5747 	AbsoluteTime                    startTime, elapsedTime;
5748 	uint32_t                        deltaTime;
5749 
5750 	ctx = (HaltRestartApplierContext *) context;
5751 
5752 	_IOServiceInterestNotifier * notifier;
5753 	notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5754 	memset(&notify, 0, sizeof(notify));
5755 	notify.powerRef    = (void *)(uintptr_t)ctx->Counter;
5756 	notify.returnValue = 0;
5757 	notify.stateNumber = ctx->PowerState;
5758 	notify.stateFlags  = ctx->PowerFlags;
5759 
5760 	if (notifier) {
5761 		ctx->handler = notifier->handler;
5762 	}
5763 
5764 	clock_get_uptime(&startTime);
5765 	ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
5766 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5767 
5768 	if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5769 		LOG("%s handler %p took %u ms\n",
5770 		    ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5771 		halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5772 	}
5773 
5774 	ctx->handler = NULL;
5775 	ctx->Counter++;
5776 }
5777 
5778 static void
5779 quiescePowerTreeCallback( void * target, void * param )
5780 {
5781 	IOLockLock(gPMHaltLock);
5782 	gPMQuiesced = true;
5783 	thread_wakeup(param);
5784 	IOLockUnlock(gPMHaltLock);
5785 }
5786 
5787 void
5788 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5789 {
5790 	AbsoluteTime                startTime, elapsedTime;
5791 	uint32_t                    deltaTime;
5792 	bool                        nvramSync = false;
5793 
5794 	memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5795 	gHaltRestartCtx.RootDomain = this;
5796 
5797 	clock_get_uptime(&startTime);
5798 	switch (pe_type) {
5799 	case kPEHaltCPU:
5800 	case kPEUPSDelayHaltCPU:
5801 		gHaltRestartCtx.PowerState  = OFF_STATE;
5802 		gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5803 		gHaltRestartCtx.LogString   = "PowerOff";
5804 		nvramSync = true;
5805 		break;
5806 
5807 	case kPERestartCPU:
5808 		gHaltRestartCtx.PowerState  = RESTART_STATE;
5809 		gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5810 		gHaltRestartCtx.LogString   = "Restart";
5811 		nvramSync = true;
5812 		break;
5813 
5814 	case kPEPagingOff:
5815 		gHaltRestartCtx.PowerState  = ON_STATE;
5816 		gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5817 		gHaltRestartCtx.LogString   = "PagingOff";
5818 		IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5819 #if HIBERNATION
5820 		IOHibernateSystemRestart();
5821 #endif
5822 		break;
5823 
5824 	default:
5825 		return;
5826 	}
5827 
5828 	if (nvramSync) {
5829 		PESyncNVRAM();
5830 	}
5831 
5832 	gHaltRestartCtx.phase = kNotifyPriorityClients;
5833 	// Notify legacy clients
5834 	applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5835 
5836 	// For normal shutdown, turn off File Server Mode.
5837 	if (kPEHaltCPU == pe_type) {
5838 		OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5839 		OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5840 		if (setting && num) {
5841 			setPMSetting(setting.get(), num.get());
5842 		}
5843 	}
5844 
5845 	if (kPEPagingOff != pe_type) {
5846 		gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5847 		// Notify in power tree order
5848 		notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5849 	}
5850 
5851 	gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5852 #if defined(XNU_TARGET_OS_OSX)
5853 	IOCPURunPlatformHaltRestartActions(pe_type);
5854 #else /* !defined(XNU_TARGET_OS_OSX) */
5855 	if (kPEPagingOff != pe_type) {
5856 		IOCPURunPlatformHaltRestartActions(pe_type);
5857 	}
5858 #endif /* !defined(XNU_TARGET_OS_OSX) */
5859 
5860 	// Wait for PM to quiesce
5861 	if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5862 		gHaltRestartCtx.phase = kQuiescePM;
5863 		AbsoluteTime quiesceTime = mach_absolute_time();
5864 
5865 		IOLockLock(gPMHaltLock);
5866 		gPMQuiesced = false;
5867 		if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5868 		    kIOReturnSuccess) {
5869 			while (!gPMQuiesced) {
5870 				IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5871 			}
5872 		}
5873 		IOLockUnlock(gPMHaltLock);
5874 		deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5875 		DLOG("PM quiesce took %u ms\n", deltaTime);
5876 		halt_log_enter("Quiesce", NULL, elapsedTime);
5877 	}
5878 	gHaltRestartCtx.phase = kNotifyDone;
5879 
5880 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5881 	LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5882 
5883 	halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5884 
5885 	deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5886 	LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5887 
5888 	if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5889 		printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5890 	}
5891 
5892 	checkShutdownTimeout();
5893 }
5894 
5895 bool
5896 IOPMrootDomain::checkShutdownTimeout()
5897 {
5898 	AbsoluteTime   elapsedTime;
5899 	uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5900 
5901 	if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5902 		return true;
5903 	}
5904 	return false;
5905 }
5906 
5907 void
5908 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5909 {
5910 	if (gHaltLog) {
5911 		if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5912 			halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5913 		}
5914 		panic("%s timed out in phase '%s'. Total %d ms:%s",
5915 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5916 	} else {
5917 		panic("%s timed out in phase \'%s\'. Total %d ms",
5918 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5919 	}
5920 }
5921 
5922 //******************************************************************************
5923 // shutdownSystem
5924 //
5925 //******************************************************************************
5926 
5927 IOReturn
5928 IOPMrootDomain::shutdownSystem( void )
5929 {
5930 	return kIOReturnUnsupported;
5931 }
5932 
5933 //******************************************************************************
5934 // restartSystem
5935 //
5936 //******************************************************************************
5937 
5938 IOReturn
5939 IOPMrootDomain::restartSystem( void )
5940 {
5941 	return kIOReturnUnsupported;
5942 }
5943 
5944 // MARK: -
5945 // MARK: System Capability
5946 
5947 //******************************************************************************
5948 // tagPowerPlaneService
5949 //
5950 // Running on PM work loop thread.
5951 //******************************************************************************
5952 
5953 void
5954 IOPMrootDomain::tagPowerPlaneService(
5955 	IOService *         service,
5956 	IOPMActions *       actions,
5957 	IOPMPowerStateIndex maxPowerState )
5958 {
5959 	uint32_t    flags = 0;
5960 
5961 	memset(actions, 0, sizeof(*actions));
5962 	actions->target = this;
5963 
5964 	if (service == this) {
5965 		actions->actionPowerChangeStart =
5966 		    OSMemberFunctionCast(
5967 			IOPMActionPowerChangeStart, this,
5968 			&IOPMrootDomain::handleOurPowerChangeStart);
5969 
5970 		actions->actionPowerChangeDone =
5971 		    OSMemberFunctionCast(
5972 			IOPMActionPowerChangeDone, this,
5973 			&IOPMrootDomain::handleOurPowerChangeDone);
5974 
5975 		actions->actionPowerChangeOverride =
5976 		    OSMemberFunctionCast(
5977 			IOPMActionPowerChangeOverride, this,
5978 			&IOPMrootDomain::overrideOurPowerChange);
5979 		return;
5980 	}
5981 
5982 #if DISPLAY_WRANGLER_PRESENT
5983 	if (NULL != service->metaCast("IODisplayWrangler")) {
5984 		// XXX should this really retain?
5985 		wrangler.reset(service, OSRetain);
5986 		wrangler->registerInterest(gIOGeneralInterest,
5987 		    &displayWranglerNotification, this, NULL);
5988 
5989 		// found the display wrangler, check for any display assertions already created
5990 		if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5991 			DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5992 			wrangler->setIgnoreIdleTimer( true );
5993 		}
5994 		flags |= kPMActionsFlagIsDisplayWrangler;
5995 	}
5996 #endif /* DISPLAY_WRANGLER_PRESENT */
5997 
5998 	if (service->propertyExists("IOPMStrictTreeOrder")) {
5999 		flags |= kPMActionsFlagIsGraphicsDriver;
6000 	}
6001 	if (service->propertyExists("IOPMUnattendedWakePowerState")) {
6002 		flags |= kPMActionsFlagIsAudioDriver;
6003 	}
6004 
6005 	// Find the power connection object that is a child of the PCI host
6006 	// bridge, and has a graphics/audio device attached below. Mark the
6007 	// power branch for delayed child notifications.
6008 
6009 	if (flags) {
6010 		IORegistryEntry * child  = service;
6011 		IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
6012 
6013 		while (child != this) {
6014 			if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
6015 				// Skip delaying notifications and clamping power on external graphics and audio devices.
6016 				DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
6017 				flags = 0;
6018 				break;
6019 			}
6020 			if ((parent == pciHostBridgeDriver) ||
6021 			    (parent == this)) {
6022 				if (OSDynamicCast(IOPowerConnection, child)) {
6023 					IOPowerConnection * conn = (IOPowerConnection *) child;
6024 					conn->delayChildNotification = true;
6025 					DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6026 				}
6027 				break;
6028 			}
6029 			child = parent;
6030 			parent = child->getParentEntry(gIOPowerPlane);
6031 		}
6032 	}
6033 
6034 	OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6035 	if (prop) {
6036 		OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6037 		if (num) {
6038 			actions->darkWakePowerState = num->unsigned32BitValue();
6039 			if (actions->darkWakePowerState < maxPowerState) {
6040 				flags |= kPMActionsFlagHasDarkWakePowerState;
6041 			}
6042 		}
6043 	}
6044 
6045 
6046 	if (flags) {
6047 		DLOG("%s tag flags %x\n", service->getName(), flags);
6048 		actions->flags |= flags;
6049 		actions->actionPowerChangeOverride =
6050 		    OSMemberFunctionCast(
6051 			IOPMActionPowerChangeOverride, this,
6052 			&IOPMrootDomain::overridePowerChangeForService);
6053 
6054 		if (flags & kPMActionsFlagIsDisplayWrangler) {
6055 			actions->actionActivityTickle =
6056 			    OSMemberFunctionCast(
6057 				IOPMActionActivityTickle, this,
6058 				&IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6059 
6060 			actions->actionUpdatePowerClient =
6061 			    OSMemberFunctionCast(
6062 				IOPMActionUpdatePowerClient, this,
6063 				&IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6064 		}
6065 		return;
6066 	}
6067 
6068 	// Locate the first PCI host bridge for PMTrace.
6069 	if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6070 		IOService * provider = service->getProvider();
6071 		if (OSDynamicCast(IOPlatformDevice, provider) &&
6072 		    provider->inPlane(gIODTPlane)) {
6073 			pciHostBridgeDevice.reset(provider, OSNoRetain);
6074 			pciHostBridgeDriver.reset(service, OSNoRetain);
6075 			DLOG("PMTrace found PCI host bridge %s->%s\n",
6076 			    provider->getName(), service->getName());
6077 		}
6078 	}
6079 
6080 	// Tag top-level PCI devices. The order of PMinit() call does not
6081 	// change across boots and is used as the PCI bit number.
6082 	if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6083 		// Would prefer to check built-in property, but tagPowerPlaneService()
6084 		// is called before pciDevice->registerService().
6085 		IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6086 		if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6087 			int bit = pmTracer->recordTopLevelPCIDevice( service );
6088 			if (bit >= 0) {
6089 				// Save the assigned bit for fast lookup.
6090 				actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6091 
6092 				actions->actionPowerChangeStart =
6093 				    OSMemberFunctionCast(
6094 					IOPMActionPowerChangeStart, this,
6095 					&IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6096 
6097 				actions->actionPowerChangeDone =
6098 				    OSMemberFunctionCast(
6099 					IOPMActionPowerChangeDone, this,
6100 					&IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6101 			}
6102 		}
6103 	}
6104 }
6105 
6106 //******************************************************************************
6107 // PM actions for root domain
6108 //******************************************************************************
6109 
6110 void
6111 IOPMrootDomain::overrideOurPowerChange(
6112 	IOService *             service,
6113 	IOPMActions *           actions,
6114 	const IOPMRequest *     request,
6115 	IOPMPowerStateIndex *   inOutPowerState,
6116 	IOPMPowerChangeFlags *  inOutChangeFlags )
6117 {
6118 	uint32_t changeFlags = *inOutChangeFlags;
6119 	uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6120 	uint32_t currentPowerState = (uint32_t) getPowerState();
6121 
6122 	if (request->getTag() == 0) {
6123 		// Set a tag for any request that originates from IOServicePM
6124 		(const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6125 	}
6126 
6127 	DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6128 	    getPowerStateString(currentPowerState),
6129 	    getPowerStateString(desiredPowerState),
6130 	    _currentCapability, changeFlags,
6131 	    request->getTag());
6132 
6133 
6134 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6135 	/*
6136 	 * ASBM send lowBattery notifications every 1 second until the device
6137 	 * enters hibernation. This queues up multiple sleep requests.
6138 	 * After the device wakes from hibernation, none of these previously
6139 	 * queued sleep requests are valid.
6140 	 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6141 	 * and is cleared at the very last point in sleep.
6142 	 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6143 	 * lowBatteryCondition is invalid
6144 	 */
6145 	if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6146 		if (!lowBatteryCondition) {
6147 			DLOG("Duplicate lowBattery sleep");
6148 			*inOutChangeFlags |= kIOPMNotDone;
6149 			return;
6150 		}
6151 	}
6152 #endif
6153 
6154 	if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6155 		// Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6156 		*inOutChangeFlags |= kIOPMNotDone;
6157 		return;
6158 	}
6159 
6160 	if (changeFlags & kIOPMParentInitiated) {
6161 		// Root parent is permanently pegged at max power,
6162 		// a parent initiated power change is unexpected.
6163 		*inOutChangeFlags |= kIOPMNotDone;
6164 		return;
6165 	}
6166 
6167 #if HIBERNATION && defined(__arm64__)
6168 	if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6169 		if (!ml_is_secure_hib_supported()) {
6170 			// If hibernation is unsupported, reject sleep requests to avoid
6171 			// racing with system shutdown.
6172 			*inOutChangeFlags |= kIOPMNotDone;
6173 			return;
6174 		}
6175 	}
6176 #endif /* HIBERNATION && defined(__arm64__) */
6177 
6178 	if (desiredPowerState < currentPowerState) {
6179 		if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6180 			// Root domain is dropping power state from ON->SLEEP.
6181 			// If system is in full wake, first enter dark wake by
6182 			// converting the power drop to a capability change.
6183 			// Once in dark wake, transition to sleep state ASAP.
6184 
6185 			darkWakeToSleepASAP = true;
6186 
6187 			// Drop graphics and audio capability
6188 			_desiredCapability &= ~(
6189 				kIOPMSystemCapabilityGraphics |
6190 				kIOPMSystemCapabilityAudio);
6191 
6192 			// Convert to capability change (ON->ON)
6193 			*inOutPowerState = getRUN_STATE();
6194 			*inOutChangeFlags |= kIOPMSynchronize;
6195 
6196 			// Revert device desire from SLEEP to ON
6197 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6198 		} else {
6199 			// System is already in dark wake, ok to drop power state.
6200 			// Broadcast root power down to entire tree.
6201 			*inOutChangeFlags |= kIOPMRootChangeDown;
6202 		}
6203 	} else if (desiredPowerState > currentPowerState) {
6204 		if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6205 			// Broadcast power up when waking from sleep, but not for the
6206 			// initial power change at boot by checking for cpu capability.
6207 			*inOutChangeFlags |= kIOPMRootChangeUp;
6208 		}
6209 	}
6210 }
6211 
6212 void
6213 IOPMrootDomain::handleOurPowerChangeStart(
6214 	IOService *             service,
6215 	IOPMActions *           actions,
6216 	const IOPMRequest *     request,
6217 	IOPMPowerStateIndex     newPowerState,
6218 	IOPMPowerChangeFlags *  inOutChangeFlags )
6219 {
6220 	IOPMRequestTag requestTag = request->getTag();
6221 	IOPMRequestTag sleepReason;
6222 
6223 	uint32_t changeFlags        = *inOutChangeFlags;
6224 	uint32_t currentPowerState  = (uint32_t) getPowerState();
6225 	bool     publishSleepReason = false;
6226 
6227 	// Check if request has a valid sleep reason
6228 	sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6229 	if (sleepReason < kIOPMSleepReasonClamshell) {
6230 		sleepReason = kIOPMSleepReasonIdle;
6231 	}
6232 
6233 	_systemTransitionType    = kSystemTransitionNone;
6234 	_systemMessageClientMask = 0;
6235 	capabilityLoss           = false;
6236 	toldPowerdCapWillChange  = false;
6237 
6238 	// Emergency notifications may arrive after the initial sleep request
6239 	// has been queued. Override the sleep reason so powerd and others can
6240 	// treat this as an emergency sleep.
6241 	if (lowBatteryCondition) {
6242 		sleepReason = kIOPMSleepReasonLowPower;
6243 	} else if (thermalEmergencyState) {
6244 		sleepReason = kIOPMSleepReasonThermalEmergency;
6245 	}
6246 
6247 	// 1. Explicit capability change.
6248 	if (changeFlags & kIOPMSynchronize) {
6249 		if (newPowerState == ON_STATE) {
6250 			if (changeFlags & kIOPMSyncNoChildNotify) {
6251 				_systemTransitionType = kSystemTransitionNewCapClient;
6252 			} else {
6253 				_systemTransitionType = kSystemTransitionCapability;
6254 			}
6255 		}
6256 	}
6257 	// 2. Going to sleep (cancellation still possible).
6258 	else if (newPowerState < currentPowerState) {
6259 		_systemTransitionType = kSystemTransitionSleep;
6260 	}
6261 	// 3. Woke from (idle or demand) sleep.
6262 	else if (!systemBooting &&
6263 	    (changeFlags & kIOPMSelfInitiated) &&
6264 	    (newPowerState > currentPowerState)) {
6265 		_systemTransitionType = kSystemTransitionWake;
6266 		_desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6267 
6268 		// Early exit from dark wake to full (e.g. LID open)
6269 		if (kFullWakeReasonNone != fullWakeReason) {
6270 			_desiredCapability |= (
6271 				kIOPMSystemCapabilityGraphics |
6272 				kIOPMSystemCapabilityAudio);
6273 
6274 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6275 			if (fullWakeReason == kFullWakeReasonLocalUser) {
6276 				darkWakeExit = true;
6277 				darkWakeToSleepASAP = false;
6278 				setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6279 				    kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6280 			}
6281 #endif
6282 		}
6283 #if HIBERNATION
6284 		IOHibernateSetWakeCapabilities(_desiredCapability);
6285 #endif
6286 	}
6287 
6288 	// Update pending wake capability at the beginning of every
6289 	// state transition (including synchronize). This will become
6290 	// the current capability at the end of the transition.
6291 
6292 	if (kSystemTransitionSleep == _systemTransitionType) {
6293 		_pendingCapability = 0;
6294 		capabilityLoss = true;
6295 	} else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6296 		_pendingCapability = _desiredCapability |
6297 		    kIOPMSystemCapabilityCPU |
6298 		    kIOPMSystemCapabilityNetwork;
6299 
6300 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6301 			_pendingCapability |= kIOPMSystemCapabilityAudio;
6302 		}
6303 
6304 		if ((kSystemTransitionCapability == _systemTransitionType) &&
6305 		    (_pendingCapability == _currentCapability)) {
6306 			// Cancel the PM state change.
6307 			_systemTransitionType = kSystemTransitionNone;
6308 			*inOutChangeFlags |= kIOPMNotDone;
6309 		}
6310 		if (__builtin_popcount(_pendingCapability) <
6311 		    __builtin_popcount(_currentCapability)) {
6312 			capabilityLoss = true;
6313 		}
6314 	}
6315 
6316 	// 1. Capability change.
6317 	if (kSystemTransitionCapability == _systemTransitionType) {
6318 		// Dark to Full transition.
6319 		if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6320 			tracePoint( kIOPMTracePointDarkWakeExit );
6321 
6322 #if defined(XNU_TARGET_OS_OSX)
6323 			// rdar://problem/65627936
6324 			// When a dark->full wake promotion is scheduled before an ON->SLEEP
6325 			// power state drop, invalidate any request to drop power state already
6326 			// in the queue, including the override variant, unless full wake cannot
6327 			// be sustained. Any power state drop queued after this SustainFullWake
6328 			// request will not be affected.
6329 			if (checkSystemCanSustainFullWake()) {
6330 				changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6331 			}
6332 #endif
6333 
6334 			willEnterFullWake();
6335 		}
6336 
6337 		// Full to Dark transition.
6338 		if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6339 			// Clear previous stats
6340 			IOLockLock(pmStatsLock);
6341 			if (pmStatsAppResponses) {
6342 				pmStatsAppResponses = OSArray::withCapacity(5);
6343 			}
6344 			IOLockUnlock(pmStatsLock);
6345 
6346 			tracePoint( kIOPMTracePointDarkWakeEntry );
6347 			*inOutChangeFlags |= kIOPMSyncTellPowerDown;
6348 			_systemMessageClientMask = kSystemMessageClientPowerd |
6349 			    kSystemMessageClientLegacyApp;
6350 
6351 			// rdar://15971327
6352 			// Prevent user active transitions before notifying clients
6353 			// that system will sleep.
6354 			preventTransitionToUserActive(true);
6355 
6356 			IOService::setAdvisoryTickleEnable( false );
6357 
6358 			// Publish the sleep reason for full to dark wake
6359 			publishSleepReason = true;
6360 			lastSleepReason = fullToDarkReason = sleepReason;
6361 
6362 			// Publish a UUID for the Sleep --> Wake cycle
6363 			handlePublishSleepWakeUUID(true);
6364 			if (sleepDelaysReport) {
6365 				clock_get_uptime(&ts_sleepStart);
6366 				DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6367 			}
6368 
6369 			darkWakeExit = false;
6370 		}
6371 	}
6372 	// 2. System sleep.
6373 	else if (kSystemTransitionSleep == _systemTransitionType) {
6374 		// Beginning of a system sleep transition.
6375 		// Cancellation is still possible.
6376 		tracePoint( kIOPMTracePointSleepStarted );
6377 
6378 		_systemMessageClientMask = kSystemMessageClientAll;
6379 		if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6380 			_systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6381 		}
6382 		if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6383 			// Kernel priority clients are only notified on the initial
6384 			// transition to full wake, so don't notify them unless system
6385 			// has gained graphics capability since the last system wake.
6386 			_systemMessageClientMask &= ~kSystemMessageClientKernel;
6387 		} else {
6388 			// System was in full wake, but the downwards power transition is driven
6389 			// by a request that originates from IOServicePM, so it isn't tagged with
6390 			// a valid system sleep reason.
6391 			if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6392 				// Publish the same reason for full to dark
6393 				sleepReason = fullToDarkReason;
6394 			}
6395 		}
6396 #if HIBERNATION
6397 		gIOHibernateState = 0;
6398 #endif
6399 
6400 		// Record the reason for dark wake back to sleep
6401 		// System may not have ever achieved full wake
6402 
6403 		publishSleepReason = true;
6404 		lastSleepReason = sleepReason;
6405 		if (sleepDelaysReport) {
6406 			clock_get_uptime(&ts_sleepStart);
6407 			DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6408 		}
6409 	}
6410 	// 3. System wake.
6411 	else if (kSystemTransitionWake == _systemTransitionType) {
6412 		tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6413 		// Clear stats about sleep
6414 
6415 		if (AOT_STATE == newPowerState) {
6416 			_pendingCapability = 0;
6417 		}
6418 
6419 		if (AOT_STATE == currentPowerState) {
6420 			// Wake events are no longer accepted after waking to AOT_STATE.
6421 			// Re-enable wake event acceptance to append wake events claimed
6422 			// during the AOT to ON_STATE transition.
6423 			acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6424 		}
6425 
6426 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6427 			willEnterFullWake();
6428 		}
6429 	}
6430 
6431 	// The only location where the sleep reason is published. At this point
6432 	// sleep can still be cancelled, but sleep reason should be published
6433 	// early for logging purposes.
6434 
6435 	if (publishSleepReason) {
6436 		static const char * IOPMSleepReasons[] =
6437 		{
6438 			kIOPMClamshellSleepKey,
6439 			kIOPMPowerButtonSleepKey,
6440 			kIOPMSoftwareSleepKey,
6441 			kIOPMOSSwitchHibernationKey,
6442 			kIOPMIdleSleepKey,
6443 			kIOPMLowPowerSleepKey,
6444 			kIOPMThermalEmergencySleepKey,
6445 			kIOPMMaintenanceSleepKey,
6446 			kIOPMSleepServiceExitKey,
6447 			kIOPMDarkWakeThermalEmergencyKey,
6448 			kIOPMNotificationWakeExitKey
6449 		};
6450 
6451 		// Record sleep cause in IORegistry
6452 		uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6453 		if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6454 			DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6455 #if DEVELOPMENT || DEBUG
6456 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6457 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6458 			    "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6459 			    );
6460 #endif /* DEVELOPMENT || DEBUG */
6461 			setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6462 		}
6463 	}
6464 
6465 	if ((kSystemTransitionNone != _systemTransitionType) &&
6466 	    (kSystemTransitionNewCapClient != _systemTransitionType)) {
6467 		_systemStateGeneration++;
6468 		systemDarkWake = false;
6469 
6470 		DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6471 		    getPowerStateString(currentPowerState),
6472 		    getPowerStateString((uint32_t) newPowerState),
6473 		    _currentCapability, _pendingCapability,
6474 		    *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6475 		    requestTag);
6476 #if DEVELOPMENT || DEBUG
6477 		if (currentPowerState != (uint32_t) newPowerState) {
6478 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6479 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6480 			    "Start Power State Trans.",
6481 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6482 			    getPowerStateString(currentPowerState),
6483 			    getPowerStateString((uint32_t) newPowerState),
6484 			    _currentCapability,
6485 			    _pendingCapability,
6486 			    *inOutChangeFlags,
6487 			    _systemStateGeneration,
6488 			    _systemMessageClientMask,
6489 			    requestTag
6490 			    );
6491 		}
6492 #endif /* DEVELOPMENT || DEBUG */
6493 	}
6494 
6495 	if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6496 		panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6497 	}
6498 	if (_aotNow && (ON_STATE == newPowerState)) {
6499 		WAKEEVENT_LOCK();
6500 		aotShouldExit(true);
6501 		WAKEEVENT_UNLOCK();
6502 		aotExit(false);
6503 	}
6504 }
6505 
6506 void
6507 IOPMrootDomain::handleOurPowerChangeDone(
6508 	IOService *             service,
6509 	IOPMActions *           actions,
6510 	const IOPMRequest *     request,
6511 	IOPMPowerStateIndex     oldPowerState,
6512 	IOPMPowerChangeFlags    changeFlags )
6513 {
6514 	if (kSystemTransitionNewCapClient == _systemTransitionType) {
6515 		_systemTransitionType = kSystemTransitionNone;
6516 		return;
6517 	}
6518 
6519 	if (_systemTransitionType != kSystemTransitionNone) {
6520 		uint32_t currentPowerState = (uint32_t) getPowerState();
6521 
6522 		if (changeFlags & kIOPMNotDone) {
6523 			// Power down was cancelled or vetoed.
6524 			_pendingCapability = _currentCapability;
6525 			lastSleepReason = 0;
6526 
6527 			// When sleep is cancelled or reverted, don't report
6528 			// the target (lower) power state as the previous state.
6529 			oldPowerState = currentPowerState;
6530 
6531 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6532 			    CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6533 #if defined(XNU_TARGET_OS_OSX)
6534 				pmPowerStateQueue->submitPowerEvent(
6535 					kPowerEventPolicyStimulus,
6536 					(void *) kStimulusDarkWakeReentry,
6537 					_systemStateGeneration );
6538 #else /* !defined(XNU_TARGET_OS_OSX) */
6539 				// On embedded, there are no factors that can prolong a
6540 				// "darkWake" when a power down is vetoed. We need to
6541 				// promote to "fullWake" at least once so that factors
6542 				// that prevent idle sleep can assert themselves if required
6543 				pmPowerStateQueue->submitPowerEvent(
6544 					kPowerEventPolicyStimulus,
6545 					(void *) kStimulusDarkWakeActivityTickle);
6546 #endif /* !defined(XNU_TARGET_OS_OSX) */
6547 			}
6548 
6549 			// Revert device desire to max.
6550 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6551 		} else {
6552 			// Send message on dark wake to full wake promotion.
6553 			// tellChangeUp() handles the normal SLEEP->ON case.
6554 
6555 			if (kSystemTransitionCapability == _systemTransitionType) {
6556 				if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6557 					lastSleepReason = 0; // stop logging wrangler tickles
6558 					tellClients(kIOMessageSystemHasPoweredOn);
6559 				}
6560 				if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6561 					// Going dark, reset full wake state
6562 					// userIsActive will be cleared by wrangler powering down
6563 					fullWakeReason = kFullWakeReasonNone;
6564 
6565 					if (ts_sleepStart) {
6566 						clock_get_uptime(&wake2DarkwakeDelay);
6567 						SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6568 						DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6569 						ts_sleepStart = 0;
6570 					}
6571 				}
6572 			}
6573 
6574 			// Reset state after exiting from dark wake.
6575 
6576 			if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6577 			    CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6578 				darkWakeMaintenance = false;
6579 				darkWakeToSleepASAP = false;
6580 				pciCantSleepValid   = false;
6581 				darkWakeSleepService = false;
6582 
6583 				if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6584 					// Remove the influence of display power assertion
6585 					// before next system wake.
6586 					if (wrangler) {
6587 						wrangler->changePowerStateForRootDomain(
6588 							kWranglerPowerStateMin );
6589 					}
6590 					removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6591 				}
6592 			}
6593 
6594 			// Entered dark mode.
6595 
6596 			if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6597 			    (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6598 				// Queue an evaluation of whether to remain in dark wake,
6599 				// and for how long. This serves the purpose of draining
6600 				// any assertions from the queue.
6601 
6602 				pmPowerStateQueue->submitPowerEvent(
6603 					kPowerEventPolicyStimulus,
6604 					(void *) kStimulusDarkWakeEntry,
6605 					_systemStateGeneration );
6606 			}
6607 		}
6608 
6609 #if DEVELOPMENT || DEBUG
6610 		if (currentPowerState != (uint32_t) oldPowerState) {
6611 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6612 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6613 			    "Finish Power State Trans.",
6614 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6615 			    getPowerStateString((uint32_t)oldPowerState),
6616 			    getPowerStateString(currentPowerState),
6617 			    _currentCapability,
6618 			    _pendingCapability,
6619 			    changeFlags,
6620 			    _systemStateGeneration,
6621 			    _systemMessageClientMask,
6622 			    request->getTag()
6623 			    );
6624 		}
6625 #endif /* DEVELOPMENT || DEBUG */
6626 
6627 		DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6628 		    getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6629 		    _currentCapability, _pendingCapability,
6630 		    changeFlags, _systemStateGeneration, _systemMessageClientMask,
6631 		    request->getTag());
6632 
6633 		if ((currentPowerState == ON_STATE) && pmAssertions) {
6634 			pmAssertions->reportCPUBitAccounting();
6635 		}
6636 
6637 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6638 			displayWakeCnt++;
6639 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6640 			if (clamshellExists && fullWakeThreadCall) {
6641 				AbsoluteTime deadline;
6642 				clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6643 				thread_call_enter_delayed(fullWakeThreadCall, deadline);
6644 			}
6645 #endif
6646 		} else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6647 			darkWakeCnt++;
6648 		}
6649 
6650 		// Update current system capability.
6651 		if (_currentCapability != _pendingCapability) {
6652 			_currentCapability = _pendingCapability;
6653 		}
6654 
6655 		// Update highest system capability.
6656 
6657 		_highestCapability |= _currentCapability;
6658 
6659 		if (darkWakePostTickle &&
6660 		    (kSystemTransitionWake == _systemTransitionType) &&
6661 		    (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6662 		    kDarkWakeFlagPromotionLate) {
6663 			darkWakePostTickle = false;
6664 			reportUserInput();
6665 		} else if (darkWakeExit) {
6666 			requestFullWake( kFullWakeReasonLocalUser );
6667 		}
6668 
6669 		// Reset tracepoint at completion of capability change,
6670 		// completion of wake transition, and aborted sleep transition.
6671 
6672 		if ((_systemTransitionType == kSystemTransitionCapability) ||
6673 		    (_systemTransitionType == kSystemTransitionWake) ||
6674 		    ((_systemTransitionType == kSystemTransitionSleep) &&
6675 		    (changeFlags & kIOPMNotDone))) {
6676 			setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6677 			tracePoint( kIOPMTracePointSystemUp );
6678 		}
6679 
6680 		_systemTransitionType = kSystemTransitionNone;
6681 		_systemMessageClientMask = 0;
6682 		toldPowerdCapWillChange  = false;
6683 
6684 		darkWakeLogClamp = false;
6685 
6686 		if (lowBatteryCondition) {
6687 			privateSleepSystem(kIOPMSleepReasonLowPower);
6688 		} else if (thermalEmergencyState) {
6689 			privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6690 		} else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6691 			// Request for full wake is removed while system is waking up to full wake
6692 			DLOG("DisplayOn fullwake request is removed\n");
6693 			handleSetDisplayPowerOn(false);
6694 		}
6695 
6696 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6697 			pmPowerStateQueue->submitPowerEvent(
6698 				kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6699 		}
6700 	}
6701 }
6702 
6703 //******************************************************************************
6704 // PM actions for graphics and audio.
6705 //******************************************************************************
6706 
6707 void
6708 IOPMrootDomain::overridePowerChangeForService(
6709 	IOService *             service,
6710 	IOPMActions *           actions,
6711 	const IOPMRequest *     request,
6712 	IOPMPowerStateIndex *   inOutPowerState,
6713 	IOPMPowerChangeFlags *  inOutChangeFlags )
6714 {
6715 	uint32_t powerState  = (uint32_t) *inOutPowerState;
6716 	uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6717 	const uint32_t actionFlags = actions->flags;
6718 
6719 	if (kSystemTransitionNone == _systemTransitionType) {
6720 		// Not in midst of a system transition.
6721 		// Do not set kPMActionsStatePowerClamped.
6722 	} else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6723 		bool enableClamp = false;
6724 
6725 		// For most drivers, enable the clamp during ON->Dark transition
6726 		// which has the kIOPMSynchronize flag set in changeFlags.
6727 		if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6728 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6729 		    (changeFlags & kIOPMSynchronize)) {
6730 			enableClamp = true;
6731 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6732 		    ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6733 		    ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6734 		    (changeFlags & kIOPMSynchronize)) {
6735 			enableClamp = true;
6736 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6737 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6738 		    (changeFlags & kIOPMSynchronize)) {
6739 			enableClamp = true;
6740 		} else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6741 		    (_systemTransitionType == kSystemTransitionSleep)) {
6742 			// For graphics drivers, clamp power when entering
6743 			// system sleep. Not when dropping to dark wake.
6744 			enableClamp = true;
6745 		}
6746 
6747 		if (enableClamp) {
6748 			actions->state |= kPMActionsStatePowerClamped;
6749 			DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6750 			    service->getName(), service->getRegistryEntryID(),
6751 			    _pendingCapability, powerState, changeFlags);
6752 		}
6753 	} else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6754 		bool disableClamp = false;
6755 
6756 		if ((actionFlags & (
6757 			    kPMActionsFlagIsDisplayWrangler |
6758 			    kPMActionsFlagIsGraphicsDriver)) &&
6759 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6760 			disableClamp = true;
6761 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6762 		    (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6763 			disableClamp = true;
6764 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6765 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6766 			disableClamp = true;
6767 		}
6768 
6769 		if (disableClamp) {
6770 			actions->state &= ~kPMActionsStatePowerClamped;
6771 			DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6772 			    service->getName(), service->getRegistryEntryID(),
6773 			    _pendingCapability, powerState, changeFlags);
6774 		}
6775 	}
6776 
6777 	if (actions->state & kPMActionsStatePowerClamped) {
6778 		uint32_t maxPowerState = 0;
6779 
6780 		// Determine the max power state allowed when clamp is enabled
6781 		if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6782 			// Parent intiated power state changes
6783 			if ((service->getPowerState() > maxPowerState) &&
6784 			    (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6785 				maxPowerState++;
6786 
6787 				// Remove lingering effects of any tickle before entering
6788 				// dark wake. It will take a new tickle to return to full
6789 				// wake, so the existing tickle state is useless.
6790 
6791 				if (changeFlags & kIOPMDomainDidChange) {
6792 					*inOutChangeFlags |= kIOPMExpireIdleTimer;
6793 				}
6794 			} else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6795 				maxPowerState++;
6796 			} else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6797 				maxPowerState = actions->darkWakePowerState;
6798 			}
6799 		} else {
6800 			// Deny all self-initiated changes when power is limited.
6801 			// Wrangler tickle should never defeat the limiter.
6802 			maxPowerState = service->getPowerState();
6803 		}
6804 
6805 		if (powerState > maxPowerState) {
6806 			DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6807 			    service->getName(), service->getRegistryEntryID(),
6808 			    powerState, maxPowerState, changeFlags);
6809 			*inOutPowerState = maxPowerState;
6810 
6811 			if (darkWakePostTickle &&
6812 			    (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6813 			    (changeFlags & kIOPMDomainWillChange) &&
6814 			    ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6815 			    kDarkWakeFlagPromotionEarly)) {
6816 				darkWakePostTickle = false;
6817 				reportUserInput();
6818 			}
6819 		}
6820 
6821 		if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6822 			if (darkWakeLogClamp) {
6823 				AbsoluteTime    now;
6824 				uint64_t        nsec;
6825 
6826 				clock_get_uptime(&now);
6827 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6828 				absolutetime_to_nanoseconds(now, &nsec);
6829 				DLOG("dark wake power clamped after %u ms\n",
6830 				    ((int)((nsec) / NSEC_PER_MSEC)));
6831 			}
6832 			darkWakePowerClamped = true;
6833 		}
6834 	}
6835 }
6836 
6837 void
6838 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6839 	IOService *     service,
6840 	IOPMActions *   actions )
6841 {
6842 #if DISPLAY_WRANGLER_PRESENT
6843 	// Warning: Not running in PM work loop context - don't modify state !!!
6844 	// Trap tickle directed to IODisplayWrangler while running with graphics
6845 	// capability suppressed.
6846 
6847 	assert(service == wrangler);
6848 
6849 	clock_get_uptime(&userActivityTime);
6850 	bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6851 	    || (lastSleepReason == kIOPMSleepReasonMaintenance)
6852 	    || (lastSleepReason == kIOPMSleepReasonSoftware));
6853 	if (aborting) {
6854 		userActivityCount++;
6855 		DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6856 		    userActivityCount, lastSleepReason);
6857 	}
6858 
6859 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6860 		DLOG("display wrangler tickled\n");
6861 		if (kIOLogPMRootDomain & gIOKitDebug) {
6862 			OSReportWithBacktrace("Dark wake display tickle");
6863 		}
6864 		if (pmPowerStateQueue) {
6865 			pmPowerStateQueue->submitPowerEvent(
6866 				kPowerEventPolicyStimulus,
6867 				(void *) kStimulusDarkWakeActivityTickle,
6868 				true /* set wake type */ );
6869 		}
6870 	}
6871 #endif /* DISPLAY_WRANGLER_PRESENT */
6872 }
6873 
6874 void
6875 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6876 	IOService *             service,
6877 	IOPMActions *           actions,
6878 	const OSSymbol *        powerClient,
6879 	IOPMPowerStateIndex     oldPowerState,
6880 	IOPMPowerStateIndex     newPowerState )
6881 {
6882 #if DISPLAY_WRANGLER_PRESENT
6883 	assert(service == wrangler);
6884 
6885 	// This function implements half of the user active detection
6886 	// by monitoring changes to the display wrangler's device desire.
6887 	//
6888 	// User becomes active when either:
6889 	// 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6890 	//    in max power state. This desire change in absence of a power state
6891 	//    change is detected within. This handles the case when user becomes
6892 	//    active while the display is already lit by setDisplayPowerOn().
6893 	//
6894 	// 2. Power state change to max, and DeviceDesire is also at max.
6895 	//    Handled by displayWranglerNotification().
6896 	//
6897 	// User becomes inactive when DeviceDesire drops to sleep state or below.
6898 
6899 	DLOG("wrangler %s (ps %u, %u->%u)\n",
6900 	    powerClient->getCStringNoCopy(),
6901 	    (uint32_t) service->getPowerState(),
6902 	    (uint32_t) oldPowerState, (uint32_t) newPowerState);
6903 
6904 	if (powerClient == gIOPMPowerClientDevice) {
6905 		if ((newPowerState > oldPowerState) &&
6906 		    (newPowerState == kWranglerPowerStateMax) &&
6907 		    (service->getPowerState() == kWranglerPowerStateMax)) {
6908 			evaluatePolicy( kStimulusEnterUserActiveState );
6909 		} else if ((newPowerState < oldPowerState) &&
6910 		    (newPowerState <= kWranglerPowerStateSleep)) {
6911 			evaluatePolicy( kStimulusLeaveUserActiveState );
6912 		}
6913 	}
6914 
6915 	if (newPowerState <= kWranglerPowerStateSleep) {
6916 		evaluatePolicy( kStimulusDisplayWranglerSleep );
6917 	} else if (newPowerState == kWranglerPowerStateMax) {
6918 		evaluatePolicy( kStimulusDisplayWranglerWake );
6919 	}
6920 #endif /* DISPLAY_WRANGLER_PRESENT */
6921 }
6922 
6923 //******************************************************************************
6924 // User active state management
6925 //******************************************************************************
6926 
6927 void
6928 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6929 {
6930 #if DISPLAY_WRANGLER_PRESENT
6931 	_preventUserActive = prevent;
6932 	if (wrangler && !_preventUserActive) {
6933 		// Allowing transition to user active, but the wrangler may have
6934 		// already powered ON in case of sleep cancel/revert. Poll the
6935 		// same conditions checked for in displayWranglerNotification()
6936 		// to bring the user active state up to date.
6937 
6938 		if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6939 		    (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6940 		    kWranglerPowerStateMax)) {
6941 			evaluatePolicy( kStimulusEnterUserActiveState );
6942 		}
6943 	}
6944 #endif /* DISPLAY_WRANGLER_PRESENT */
6945 }
6946 
6947 //******************************************************************************
6948 // Approve usage of delayed child notification by PM.
6949 //******************************************************************************
6950 
6951 bool
6952 IOPMrootDomain::shouldDelayChildNotification(
6953 	IOService * service )
6954 {
6955 	if ((kFullWakeReasonNone == fullWakeReason) &&
6956 	    (kSystemTransitionWake == _systemTransitionType)) {
6957 		DLOG("%s: delay child notify\n", service->getName());
6958 		return true;
6959 	}
6960 	return false;
6961 }
6962 
6963 //******************************************************************************
6964 // PM actions for PCI device.
6965 //******************************************************************************
6966 
6967 void
6968 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6969 	IOService *             service,
6970 	IOPMActions *           actions,
6971 	const IOPMRequest *     request,
6972 	IOPMPowerStateIndex     powerState,
6973 	IOPMPowerChangeFlags *  inOutChangeFlags )
6974 {
6975 	pmTracer->tracePCIPowerChange(
6976 		PMTraceWorker::kPowerChangeStart,
6977 		service, *inOutChangeFlags,
6978 		(actions->flags & kPMActionsPCIBitNumberMask));
6979 }
6980 
6981 void
6982 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6983 	IOService *             service,
6984 	IOPMActions *           actions,
6985 	const IOPMRequest *     request,
6986 	IOPMPowerStateIndex     powerState,
6987 	IOPMPowerChangeFlags    changeFlags )
6988 {
6989 	pmTracer->tracePCIPowerChange(
6990 		PMTraceWorker::kPowerChangeCompleted,
6991 		service, changeFlags,
6992 		(actions->flags & kPMActionsPCIBitNumberMask));
6993 }
6994 
6995 //******************************************************************************
6996 // registerInterest
6997 //
6998 // Override IOService::registerInterest() for root domain clients.
6999 //******************************************************************************
7000 
7001 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
7002 {
7003 	friend class IOPMrootDomain;
7004 	OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
7005 
7006 protected:
7007 	uint32_t        ackTimeoutCnt;
7008 	uint32_t        msgType;    // Last type seen by the message filter
7009 	uint32_t        lastSleepWakeMsgType;
7010 	uint32_t        msgIndex;
7011 	uint32_t        maxMsgDelayMS;
7012 	uint32_t        maxAckDelayMS;
7013 	uint64_t        msgAbsTime;
7014 	uint64_t        uuid0;
7015 	uint64_t        uuid1;
7016 	OSSharedPtr<const OSSymbol> identifier;
7017 	OSSharedPtr<const OSSymbol> clientName;
7018 };
7019 
7020 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
7021 
7022 OSSharedPtr<IONotifier>
7023 IOPMrootDomain::registerInterest(
7024 	const OSSymbol * typeOfInterest,
7025 	IOServiceInterestHandler handler,
7026 	void * target, void * ref )
7027 {
7028 	IOPMServiceInterestNotifier* notifier;
7029 	bool            isSystemCapabilityClient;
7030 	bool            isKernelCapabilityClient;
7031 	IOReturn        rc = kIOReturnError;
7032 
7033 	isSystemCapabilityClient = typeOfInterest &&
7034 	    typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
7035 
7036 	isKernelCapabilityClient = typeOfInterest &&
7037 	    typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7038 
7039 	if (isSystemCapabilityClient) {
7040 		typeOfInterest = gIOAppPowerStateInterest;
7041 	}
7042 
7043 	notifier = new IOPMServiceInterestNotifier;
7044 	if (!notifier) {
7045 		return NULL;
7046 	}
7047 
7048 	if (notifier->init()) {
7049 		rc  = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7050 	}
7051 	if (rc != kIOReturnSuccess) {
7052 		OSSafeReleaseNULL(notifier);
7053 		return NULL;
7054 	}
7055 
7056 	notifier->ackTimeoutCnt = 0;
7057 
7058 	if (pmPowerStateQueue) {
7059 		if (isSystemCapabilityClient) {
7060 			notifier->retain();
7061 			if (pmPowerStateQueue->submitPowerEvent(
7062 				    kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7063 				notifier->release();
7064 			}
7065 		}
7066 
7067 		if (isKernelCapabilityClient) {
7068 			notifier->retain();
7069 			if (pmPowerStateQueue->submitPowerEvent(
7070 				    kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7071 				notifier->release();
7072 			}
7073 		}
7074 	}
7075 
7076 	OSSharedPtr<OSData> data;
7077 	uint8_t *uuid = NULL;
7078 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7079 	if (kext) {
7080 		data = kext->copyUUID();
7081 	}
7082 	if (data && (data->getLength() == sizeof(uuid_t))) {
7083 		uuid = (uint8_t *)(data->getBytesNoCopy());
7084 
7085 		notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7086 		    ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7087 		    ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7088 		notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7089 		    ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7090 		    ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7091 
7092 		notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7093 	}
7094 	return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7095 }
7096 
7097 //******************************************************************************
7098 // systemMessageFilter
7099 //
7100 //******************************************************************************
7101 
7102 bool
7103 IOPMrootDomain::systemMessageFilter(
7104 	void * object, void * arg1, void * arg2, void * arg3 )
7105 {
7106 	const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7107 	bool  isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7108 	bool  isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7109 	bool  isCapClient = false;
7110 	bool  allow = false;
7111 	OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7112 	IOPMServiceInterestNotifier *notifier;
7113 
7114 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7115 
7116 	do {
7117 		// When powerd and kernel priority clients register capability interest,
7118 		// the power tree is sync'ed to inform those clients about the current
7119 		// system capability. Only allow capability change messages during sync.
7120 		if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7121 		    (!isCapMsg || !_joinedCapabilityClients ||
7122 		    !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7123 			break;
7124 		}
7125 
7126 		// Capability change message for powerd and kernel clients
7127 		if (isCapMsg) {
7128 			// Kernel priority clients
7129 			if ((context->notifyType == kNotifyPriority) ||
7130 			    (context->notifyType == kNotifyCapabilityChangePriority)) {
7131 				isCapClient = true;
7132 			}
7133 
7134 			// powerd will maintain two client registrations with root domain.
7135 			// isCapPowerd will be TRUE for any message targeting the powerd
7136 			// exclusive (capability change) interest registration.
7137 			if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7138 				isCapClient = true;
7139 			}
7140 		}
7141 
7142 		if (isCapClient) {
7143 			IOPMSystemCapabilityChangeParameters * capArgs =
7144 			    (IOPMSystemCapabilityChangeParameters *) arg2;
7145 
7146 			if (kSystemTransitionNewCapClient == _systemTransitionType) {
7147 				capArgs->fromCapabilities = 0;
7148 				capArgs->toCapabilities = _currentCapability;
7149 				capArgs->changeFlags = 0;
7150 			} else {
7151 				capArgs->fromCapabilities = _currentCapability;
7152 				capArgs->toCapabilities = _pendingCapability;
7153 
7154 				if (context->isPreChange) {
7155 					capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7156 				} else {
7157 					capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7158 				}
7159 
7160 				if (isCapPowerd && context->isPreChange) {
7161 					toldPowerdCapWillChange = true;
7162 				}
7163 			}
7164 
7165 			// App level capability change messages must only go to powerd.
7166 			// Wait for response post-change if capabilitiy is increasing.
7167 			// Wait for response pre-change if capability is decreasing.
7168 
7169 			if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7170 			    ((capabilityLoss && context->isPreChange) ||
7171 			    (!capabilityLoss && !context->isPreChange))) {
7172 				*waitForReply = kOSBooleanTrue;
7173 			}
7174 
7175 			allow = true;
7176 			break;
7177 		}
7178 
7179 		// powerd will always receive CanSystemSleep, even for a demand sleep.
7180 		// It will also have a final chance to veto sleep after all clients
7181 		// have responded to SystemWillSleep
7182 
7183 		if ((kIOMessageCanSystemSleep == context->messageType) ||
7184 		    (kIOMessageSystemWillNotSleep == context->messageType)) {
7185 			if (isCapPowerd) {
7186 				allow = true;
7187 				break;
7188 			}
7189 
7190 			// Demand sleep, don't ask apps for permission
7191 			if (context->changeFlags & kIOPMSkipAskPowerDown) {
7192 				break;
7193 			}
7194 		}
7195 
7196 		if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7197 			if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7198 			    (fullToDarkReason == kIOPMSleepReasonIdle)) {
7199 				allow = true;
7200 			}
7201 			break;
7202 		}
7203 
7204 		// Drop capability change messages for legacy clients.
7205 		// Drop legacy system sleep messages for powerd capability interest.
7206 		if (isCapMsg || isCapPowerd) {
7207 			break;
7208 		}
7209 
7210 		// Not a capability change message.
7211 		// Perform message filtering based on _systemMessageClientMask.
7212 
7213 		if ((context->notifyType == kNotifyApps) &&
7214 		    (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7215 			if (!notifier) {
7216 				break;
7217 			}
7218 
7219 			if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7220 			    (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7221 				break; // drop any duplicate WillPowerOn for AOT devices
7222 			}
7223 
7224 			allow = true;
7225 
7226 			if (waitForReply) {
7227 				if (notifier->ackTimeoutCnt >= 3) {
7228 					*waitForReply = kOSBooleanFalse;
7229 				} else {
7230 					*waitForReply = kOSBooleanTrue;
7231 				}
7232 			}
7233 		} else if ((context->notifyType == kNotifyPriority) &&
7234 		    (_systemMessageClientMask & kSystemMessageClientKernel)) {
7235 			allow = true;
7236 		}
7237 
7238 		// Check sleep/wake message ordering
7239 		if (allow) {
7240 			if (context->messageType == kIOMessageSystemWillSleep ||
7241 			    context->messageType == kIOMessageSystemWillPowerOn ||
7242 			    context->messageType == kIOMessageSystemHasPoweredOn) {
7243 				notifier->lastSleepWakeMsgType = context->messageType;
7244 			}
7245 		}
7246 	} while (false);
7247 
7248 	if (allow && isCapMsg && _joinedCapabilityClients) {
7249 		_joinedCapabilityClients->removeObject((OSObject *) object);
7250 		if (_joinedCapabilityClients->getCount() == 0) {
7251 			DMSG("destroyed capability client set %p\n",
7252 			    OBFUSCATE(_joinedCapabilityClients.get()));
7253 			_joinedCapabilityClients.reset();
7254 		}
7255 	}
7256 	if (notifier) {
7257 		// Record the last seen message type even if the message is dropped
7258 		// for traceFilteredNotification().
7259 		notifier->msgType = context->messageType;
7260 	}
7261 
7262 	return allow;
7263 }
7264 
7265 //******************************************************************************
7266 // setMaintenanceWakeCalendar
7267 //
7268 //******************************************************************************
7269 
7270 IOReturn
7271 IOPMrootDomain::setMaintenanceWakeCalendar(
7272 	const IOPMCalendarStruct * calendar )
7273 {
7274 	OSSharedPtr<OSData> data;
7275 	IOReturn ret = 0;
7276 
7277 	if (!calendar) {
7278 		return kIOReturnBadArgument;
7279 	}
7280 
7281 	data = OSData::withValue(*calendar);
7282 	if (!data) {
7283 		return kIOReturnNoMemory;
7284 	}
7285 
7286 	if (kPMCalendarTypeMaintenance == calendar->selector) {
7287 		ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7288 	} else if (kPMCalendarTypeSleepService == calendar->selector) {
7289 		ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7290 	}
7291 
7292 	return ret;
7293 }
7294 
7295 // MARK: -
7296 // MARK: Display Wrangler
7297 
7298 //******************************************************************************
7299 // displayWranglerNotification
7300 //
7301 // Handle the notification when the IODisplayWrangler changes power state.
7302 //******************************************************************************
7303 
7304 IOReturn
7305 IOPMrootDomain::displayWranglerNotification(
7306 	void * target, void * refCon,
7307 	UInt32 messageType, IOService * service,
7308 	void * messageArgument, vm_size_t argSize )
7309 {
7310 #if DISPLAY_WRANGLER_PRESENT
7311 	IOPMPowerStateIndex                 displayPowerState;
7312 	IOPowerStateChangeNotification *    params =
7313 	    (IOPowerStateChangeNotification *) messageArgument;
7314 
7315 	if ((messageType != kIOMessageDeviceWillPowerOff) &&
7316 	    (messageType != kIOMessageDeviceHasPoweredOn)) {
7317 		return kIOReturnUnsupported;
7318 	}
7319 
7320 	ASSERT_GATED();
7321 	if (!gRootDomain) {
7322 		return kIOReturnUnsupported;
7323 	}
7324 
7325 	displayPowerState = params->stateNumber;
7326 	DLOG("wrangler %s ps %d\n",
7327 	    getIOMessageString(messageType), (uint32_t) displayPowerState);
7328 
7329 	switch (messageType) {
7330 	case kIOMessageDeviceWillPowerOff:
7331 		// Display wrangler has dropped power due to display idle
7332 		// or force system sleep.
7333 		//
7334 		// 4 Display ON             kWranglerPowerStateMax
7335 		// 3 Display Dim            kWranglerPowerStateDim
7336 		// 2 Display Sleep          kWranglerPowerStateSleep
7337 		// 1 Not visible to user
7338 		// 0 Not visible to user    kWranglerPowerStateMin
7339 
7340 		if (displayPowerState <= kWranglerPowerStateSleep) {
7341 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7342 		}
7343 		break;
7344 
7345 	case kIOMessageDeviceHasPoweredOn:
7346 		// Display wrangler has powered on due to user activity
7347 		// or wake from sleep.
7348 
7349 		if (kWranglerPowerStateMax == displayPowerState) {
7350 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7351 
7352 			// See comment in handleUpdatePowerClientForDisplayWrangler
7353 			if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7354 			    kWranglerPowerStateMax) {
7355 				gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7356 			}
7357 		}
7358 		break;
7359 	}
7360 #endif /* DISPLAY_WRANGLER_PRESENT */
7361 	return kIOReturnUnsupported;
7362 }
7363 
7364 //******************************************************************************
7365 // reportUserInput
7366 //
7367 //******************************************************************************
7368 
7369 void
7370 IOPMrootDomain::updateUserActivity( void )
7371 {
7372 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7373 	clock_get_uptime(&userActivityTime);
7374 	bool aborting =  ((lastSleepReason == kIOPMSleepReasonSoftware)
7375 	    || (lastSleepReason == kIOPMSleepReasonIdle)
7376 	    || (lastSleepReason == kIOPMSleepReasonMaintenance));
7377 	if (aborting) {
7378 		userActivityCount++;
7379 		DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7380 	}
7381 #endif
7382 }
7383 void
7384 IOPMrootDomain::reportUserInput( void )
7385 {
7386 	if (wrangler) {
7387 		wrangler->activityTickle(0, 0);
7388 	}
7389 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7390 	// Update user activity
7391 	updateUserActivity();
7392 
7393 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7394 		// update user active abs time
7395 		clock_get_uptime(&gUserActiveAbsTime);
7396 		pmPowerStateQueue->submitPowerEvent(
7397 			kPowerEventPolicyStimulus,
7398 			(void *) kStimulusDarkWakeActivityTickle,
7399 			true /* set wake type */ );
7400 	}
7401 #endif
7402 }
7403 
7404 void
7405 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7406 {
7407 #if DISPLAY_WRANGLER_PRESENT
7408 	if (wrangler) {
7409 		wrangler->activityTickle(0, 0);
7410 	}
7411 #else
7412 	if (!device) {
7413 		DLOG("requestUserActive: device is null\n");
7414 		return;
7415 	}
7416 	OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7417 	uint64_t registryID = device->getRegistryEntryID();
7418 
7419 	if (!deviceName || !registryID) {
7420 		DLOG("requestUserActive: no device name or registry entry\n");
7421 		return;
7422 	}
7423 	const char *name = deviceName->getCStringNoCopy();
7424 	char payload[128];
7425 	snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7426 	DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7427 	messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7428 #endif
7429 }
7430 
7431 //******************************************************************************
7432 // latchDisplayWranglerTickle
7433 //******************************************************************************
7434 
7435 bool
7436 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7437 {
7438 #if DISPLAY_WRANGLER_PRESENT
7439 	if (latch) {
7440 		if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7441 		    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7442 		    !checkSystemCanSustainFullWake()) {
7443 			// Currently in dark wake, and not transitioning to full wake.
7444 			// Full wake is unsustainable, so latch the tickle to prevent
7445 			// the display from lighting up momentarily.
7446 			wranglerTickled = true;
7447 		} else {
7448 			wranglerTickled = false;
7449 		}
7450 	} else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7451 		wranglerTickled = false;
7452 
7453 		pmPowerStateQueue->submitPowerEvent(
7454 			kPowerEventPolicyStimulus,
7455 			(void *) kStimulusDarkWakeActivityTickle );
7456 	}
7457 
7458 	return wranglerTickled;
7459 #else  /* ! DISPLAY_WRANGLER_PRESENT */
7460 	return false;
7461 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7462 }
7463 
7464 //******************************************************************************
7465 // setDisplayPowerOn
7466 //
7467 // For root domain user client
7468 //******************************************************************************
7469 
7470 void
7471 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7472 {
7473 	pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7474 	    (void *) NULL, options );
7475 }
7476 
7477 // MARK: -
7478 // MARK: System PM Policy
7479 
7480 //******************************************************************************
7481 // checkSystemSleepAllowed
7482 //
7483 //******************************************************************************
7484 
7485 bool
7486 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7487     uint32_t     sleepReason )
7488 {
7489 	uint32_t err = 0;
7490 
7491 	// Conditions that prevent idle and demand system sleep.
7492 
7493 	do {
7494 		if (gSleepDisabledFlag) {
7495 			err = kPMConfigPreventSystemSleep;
7496 			break;
7497 		}
7498 
7499 		if (userDisabledAllSleep) {
7500 			err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7501 			break;
7502 		}
7503 
7504 		if (systemBooting || systemShutdown || gWillShutdown) {
7505 			err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7506 			break;
7507 		}
7508 
7509 		if (options == 0) {
7510 			break;
7511 		}
7512 
7513 		// Conditions above pegs the system at full wake.
7514 		// Conditions below prevent system sleep but does not prevent
7515 		// dark wake, and must be called from gated context.
7516 
7517 #if !CONFIG_SLEEP
7518 		err = kPMConfigPreventSystemSleep;    // 3. config does not support sleep
7519 		break;
7520 #endif
7521 
7522 		if (_driverKitMatchingAssertionCount != 0) {
7523 			err = kPMCPUAssertion;
7524 			break;
7525 		}
7526 
7527 		// Check for any dexts currently being added to the PM tree. Sleeping while
7528 		// this is in flight can cause IOServicePH to timeout.
7529 		if (!IOServicePH::checkPMReady()) {
7530 #if !defined(XNU_TARGET_OS_OSX)
7531 			if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
7532 				// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7533 				// in dark wake for long periods of time, which causes issues as apps were
7534 				// already informed of sleep during the f->9 transition. As a temporary
7535 				// measure, always full wake if we hit this specific condition.
7536 				pmPowerStateQueue->submitPowerEvent(
7537 					kPowerEventPolicyStimulus,
7538 					(void *) kStimulusDarkWakeActivityTickle);
7539 			}
7540 #endif
7541 			err = kPMDKNotReady;
7542 			break;
7543 		}
7544 
7545 		if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7546 			break; // always sleep on low battery or when in thermal warning/emergency state
7547 		}
7548 
7549 		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7550 			break; // always sleep on dark wake thermal emergencies
7551 		}
7552 
7553 		if (preventSystemSleepList->getCount() != 0) {
7554 			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7555 			break;
7556 		}
7557 
7558 
7559 		if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7560 		    kIOPMDriverAssertionLevelOn) {
7561 			err = kPMCPUAssertion; // 5. CPU assertion
7562 			break;
7563 		}
7564 
7565 		if (pciCantSleepValid) {
7566 			if (pciCantSleepFlag) {
7567 				err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7568 			}
7569 			break;
7570 		} else if (sleepSupportedPEFunction &&
7571 		    CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7572 			IOReturn ret;
7573 			OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7574 			ret = getPlatform()->callPlatformFunction(
7575 				sleepSupportedPEFunction.get(), false,
7576 				NULL, NULL, NULL, NULL);
7577 			pciCantSleepValid = true;
7578 			pciCantSleepFlag  = false;
7579 			if ((platformSleepSupport & kPCICantSleep) ||
7580 			    ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7581 				err = 6; // 6. PCI card does not support PM
7582 				pciCantSleepFlag = true;
7583 				break;
7584 			}
7585 		}
7586 	}while (false);
7587 
7588 	if (err) {
7589 		DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7590 		return false;
7591 	}
7592 	return true;
7593 }
7594 
7595 bool
7596 IOPMrootDomain::checkSystemSleepEnabled( void )
7597 {
7598 	return checkSystemSleepAllowed(0, 0);
7599 }
7600 
7601 bool
7602 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7603 {
7604 	ASSERT_GATED();
7605 	return checkSystemSleepAllowed(1, sleepReason);
7606 }
7607 
7608 //******************************************************************************
7609 // checkSystemCanSustainFullWake
7610 //******************************************************************************
7611 
7612 bool
7613 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7614 {
7615 	if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7616 		// Low battery wake, or received a low battery notification
7617 		// while system is awake. This condition will persist until
7618 		// the following wake.
7619 		return false;
7620 	}
7621 
7622 	if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7623 		// Graphics state is unknown and external display might not be probed.
7624 		// Do not incorporate state that requires graphics to be in max power
7625 		// such as desktopMode or clamshellDisabled.
7626 
7627 		if (!acAdaptorConnected) {
7628 			DLOG("full wake check: no AC\n");
7629 			return false;
7630 		}
7631 	}
7632 	return true;
7633 }
7634 
7635 //******************************************************************************
7636 // checkSystemCanAbortIdleSleep
7637 //******************************************************************************
7638 
7639 bool
7640 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7641 {
7642 	bool abortableSleepType =  ((lastSleepReason == kIOPMSleepReasonIdle)
7643 	    || (lastSleepReason == 0));
7644 	return idleSleepRevertible && abortableSleepType;
7645 }
7646 
7647 //******************************************************************************
7648 // attemptIdleSleepAbort
7649 //******************************************************************************
7650 
7651 bool
7652 IOPMrootDomain::attemptIdleSleepAbort( void )
7653 {
7654 	if (!gIOPMWorkLoop->inGate()) {
7655 		bool ret = gIOPMWorkLoop->runAction(
7656 			OSMemberFunctionCast(IOWorkLoop::Action, this,
7657 			&IOPMrootDomain::attemptIdleSleepAbort),
7658 			this);
7659 		return ret;
7660 	}
7661 
7662 	bool canAbort = checkSystemCanAbortIdleSleep();
7663 	if (canAbort) {
7664 		cancelIdlePowerDownSync();
7665 	} else if (lastSleepReason == kIOPMSleepReasonIdle) {
7666 		scheduleImmediateDebugWake();
7667 	}
7668 
7669 	return canAbort;
7670 }
7671 
7672 //******************************************************************************
7673 // setIdleSleepRevertible
7674 //******************************************************************************
7675 
7676 void
7677 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7678 {
7679 	idleSleepRevertible = revertible;
7680 }
7681 
7682 //******************************************************************************
7683 // mustHibernate
7684 //******************************************************************************
7685 
7686 #if HIBERNATION
7687 
7688 bool
7689 IOPMrootDomain::mustHibernate( void )
7690 {
7691 	return lowBatteryCondition || thermalWarningState;
7692 }
7693 
7694 #endif /* HIBERNATION */
7695 
7696 //******************************************************************************
7697 // AOT
7698 //******************************************************************************
7699 
7700 // Tables for accumulated days in year by month, latter used for leap years
7701 
7702 static const unsigned int daysbymonth[] =
7703 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7704 
7705 static const unsigned int lydaysbymonth[] =
7706 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7707 
7708 static int __unused
7709 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7710 {
7711 	const unsigned int *    dbm = daysbymonth;
7712 	clock_sec_t             n, x, y, z;
7713 
7714 	// Calculate seconds, minutes and hours
7715 
7716 	n = secs % (24 * 3600);
7717 	dt->second = n % 60;
7718 	n /= 60;
7719 	dt->minute = n % 60;
7720 	dt->hour = (typeof(dt->hour))(n / 60);
7721 
7722 	// Calculate day of week
7723 
7724 	n = secs / (24 * 3600);
7725 //	dt->dayWeek = (n + 4) % 7;
7726 
7727 	// Calculate year
7728 	// Rebase from days since Unix epoch (1/1/1970) store in 'n',
7729 	// to days since 1/1/1968 to start on 4 year cycle, beginning
7730 	// on a leap year.
7731 
7732 	n += (366 + 365);
7733 
7734 	// Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7735 	// Valid before 2100, since 2100 is not a leap year.
7736 
7737 	x = n / 1461;       // number of 4 year cycles
7738 	y = n % 1461;       // days into current 4 year cycle
7739 	z = 1968 + (4 * x);
7740 
7741 	// Add in years in the current 4 year cycle
7742 
7743 	if (y >= 366) {
7744 		y -= 366;   // days after the leap year
7745 		n = y % 365; // days into the current year
7746 		z += (1 + y / 365); // years after the past 4-yr cycle
7747 	} else {
7748 		n = y;
7749 		dbm = lydaysbymonth;
7750 	}
7751 	if (z > 2099) {
7752 		return 0;
7753 	}
7754 
7755 	dt->year = (typeof(dt->year))z;
7756 
7757 	// Adjust remaining days value to start at 1
7758 
7759 	n += 1;
7760 
7761 	// Calculate month
7762 
7763 	for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7764 		continue;
7765 	}
7766 	dt->month = (typeof(dt->month))x;
7767 
7768 	// Calculate day of month
7769 
7770 	dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7771 
7772 	return 1;
7773 }
7774 
7775 static clock_sec_t
7776 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7777 {
7778 	const unsigned int *    dbm = daysbymonth;
7779 	long                    y, secs, days;
7780 
7781 	if (dt->year < 1970 || dt->month > 12) {
7782 		return 0;
7783 	}
7784 
7785 	// Seconds elapsed in the current day
7786 
7787 	secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7788 
7789 	// Number of days from 1/1/70 to beginning of current year
7790 	// Account for extra day every 4 years starting at 1973
7791 
7792 	y = dt->year - 1970;
7793 	days = (y * 365) + ((y + 1) / 4);
7794 
7795 	// Change table if current year is a leap year
7796 
7797 	if ((dt->year % 4) == 0) {
7798 		dbm = lydaysbymonth;
7799 	}
7800 
7801 	// Add in days elapsed in the current year
7802 
7803 	days += (dt->day - 1) + dbm[dt->month - 1];
7804 
7805 	// Add accumulated days to accumulated seconds
7806 
7807 	secs += 24 * 3600 * days;
7808 
7809 	return secs;
7810 }
7811 
7812 unsigned long
7813 IOPMrootDomain::getRUN_STATE(void)
7814 {
7815 	return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7816 }
7817 
7818 bool
7819 IOPMrootDomain::isAOTMode()
7820 {
7821 	return _aotNow;
7822 }
7823 
7824 IOReturn
7825 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7826 {
7827 	clock_sec_t     nowsecs, wakesecs;
7828 	clock_usec_t    nowmicrosecs, wakemicrosecs;
7829 	uint64_t        nowAbs, wakeAbs;
7830 
7831 	if (!_aotMode) {
7832 		return kIOReturnNotReady;
7833 	}
7834 
7835 	clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7836 	wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7837 	if (wakeAbs < nowAbs) {
7838 		printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7839 		wakeAbs = nowAbs;
7840 	}
7841 	wakeAbs -= nowAbs;
7842 	absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7843 
7844 	wakesecs += nowsecs;
7845 	wakemicrosecs += nowmicrosecs;
7846 	if (wakemicrosecs >= USEC_PER_SEC) {
7847 		wakesecs++;
7848 		wakemicrosecs -= USEC_PER_SEC;
7849 	}
7850 	if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7851 		wakesecs++;
7852 	}
7853 
7854 	IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7855 
7856 	if (_aotWakeTimeContinuous != wakeContinuousTime) {
7857 		_aotWakeTimeContinuous = wakeContinuousTime;
7858 		IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7859 	}
7860 	_aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7861 	_aotWakeTimeUTC               = wakesecs;
7862 
7863 	return kIOReturnSuccess;
7864 }
7865 
7866 // assumes WAKEEVENT_LOCK
7867 bool
7868 IOPMrootDomain::aotShouldExit(bool software)
7869 {
7870 	bool exitNow = false;
7871 	const char * reason = "";
7872 
7873 	if (!_aotNow) {
7874 		return false;
7875 	}
7876 
7877 	if (software) {
7878 		exitNow = true;
7879 		_aotMetrics->softwareRequestCount++;
7880 		reason = "software request";
7881 	} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7882 		exitNow = true;
7883 		reason = gWakeReasonString;
7884 	} else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7885 		clock_sec_t     sec;
7886 		clock_usec_t    usec;
7887 		clock_get_calendar_microtime(&sec, &usec);
7888 		if (_calendarWakeAlarmUTC <= sec) {
7889 			exitNow = true;
7890 			_aotMetrics->rtcAlarmsCount++;
7891 			reason = "user alarm";
7892 		}
7893 	}
7894 	if (exitNow) {
7895 		_aotPendingFlags |= kIOPMWakeEventAOTExit;
7896 		IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7897 		    reason,
7898 		    _aotMetrics->sleepCount,
7899 		    _aotMetrics->possibleCount,
7900 		    _aotMetrics->confirmedPossibleCount,
7901 		    _aotMetrics->rejectedPossibleCount,
7902 		    _aotMetrics->expiredPossibleCount,
7903 		    _aotMetrics->noTimeSetCount,
7904 		    _aotMetrics->rtcAlarmsCount);
7905 	}
7906 	return exitNow;
7907 }
7908 
7909 void
7910 IOPMrootDomain::aotExit(bool cps)
7911 {
7912 	uint32_t savedMessageMask;
7913 
7914 	ASSERT_GATED();
7915 	_aotNow = false;
7916 	_aotReadyToFullWake = false;
7917 	if (_aotTimerScheduled) {
7918 		_aotTimerES->cancelTimeout();
7919 		_aotTimerScheduled = false;
7920 	}
7921 	updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7922 
7923 	_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7924 	_aotLastWakeTime = 0;
7925 	if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7926 		WAKEEVENT_LOCK();
7927 		strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7928 		    gWakeReasonString,
7929 		    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7930 		WAKEEVENT_UNLOCK();
7931 	}
7932 
7933 	_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7934 
7935 	// Preserve the message mask since a system wake transition
7936 	// may have already started and initialized the mask.
7937 	savedMessageMask = _systemMessageClientMask;
7938 	_systemMessageClientMask = kSystemMessageClientLegacyApp;
7939 	tellClients(kIOMessageSystemWillPowerOn);
7940 	_systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7941 
7942 	if (cps) {
7943 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7944 	}
7945 }
7946 
7947 void
7948 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7949 {
7950 	bool exitNow;
7951 
7952 	IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7953 
7954 	WAKEEVENT_LOCK();
7955 	exitNow = aotShouldExit(false);
7956 	if (timer != NULL) {
7957 		_aotTimerScheduled = false;
7958 	}
7959 	WAKEEVENT_UNLOCK();
7960 	if (exitNow) {
7961 		aotExit(true);
7962 	} else {
7963 #if 0
7964 		if (_aotLingerTime) {
7965 			uint64_t deadline;
7966 			IOLog("aot linger before sleep\n");
7967 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7968 			clock_delay_until(deadline);
7969 		}
7970 #endif
7971 		privateSleepSystem(kIOPMSleepReasonSoftware);
7972 	}
7973 }
7974 
7975 //******************************************************************************
7976 // adjustPowerState
7977 //
7978 // Conditions that affect our wake/sleep decision has changed.
7979 // If conditions dictate that the system must remain awake, clamp power
7980 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7981 // is TRUE, then remove the power clamp and allow the power state to drop
7982 // to SLEEP_STATE.
7983 //******************************************************************************
7984 
7985 void
7986 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7987 {
7988 	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7989 	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7990 
7991 	ASSERT_GATED();
7992 
7993 	if (_aotNow) {
7994 		bool exitNow;
7995 
7996 		if (AOT_STATE != getPowerState()) {
7997 			return;
7998 		}
7999 		WAKEEVENT_LOCK();
8000 		exitNow = aotShouldExit(false);
8001 		if (!exitNow
8002 		    && !_aotTimerScheduled
8003 		    && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8004 			_aotTimerScheduled = true;
8005 			if (_aotLingerTime) {
8006 				_aotTimerES->setTimeout(_aotLingerTime);
8007 			} else {
8008 				_aotTimerES->setTimeout(800, kMillisecondScale);
8009 			}
8010 		}
8011 		WAKEEVENT_UNLOCK();
8012 		if (exitNow) {
8013 			aotExit(true);
8014 		} else {
8015 			_aotReadyToFullWake = true;
8016 			if (!_aotTimerScheduled) {
8017 				if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8018 					// Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8019 					// Doing so will result in the sleep being cancelled anyway,
8020 					// but this check avoids unnecessary thrashing in the power state engine.
8021 					return;
8022 				}
8023 				privateSleepSystem(kIOPMSleepReasonSoftware);
8024 			}
8025 		}
8026 		return;
8027 	}
8028 
8029 	if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8030 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8031 	} else if (sleepASAP) {
8032 		changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8033 	}
8034 }
8035 
8036 void
8037 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8038 {
8039 	if (powerOn) {
8040 		if (!checkSystemCanSustainFullWake()) {
8041 			DLOG("System cannot sustain full wake\n");
8042 			return;
8043 		}
8044 
8045 		// Force wrangler to max power state. If system is in dark wake
8046 		// this alone won't raise the wrangler's power state.
8047 		if (wrangler) {
8048 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8049 		}
8050 
8051 		// System in dark wake, always requesting full wake should
8052 		// not have any bad side-effects, even if the request fails.
8053 
8054 		if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8055 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8056 			requestFullWake( kFullWakeReasonDisplayOn );
8057 		}
8058 	} else {
8059 		// Relenquish desire to power up display.
8060 		// Must first transition to state 1 since wrangler doesn't
8061 		// power off the displays at state 0. At state 0 the root
8062 		// domain is removed from the wrangler's power client list.
8063 		if (wrangler) {
8064 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8065 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8066 		}
8067 	}
8068 }
8069 
8070 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8071 
8072 //******************************************************************************
8073 // dispatchPowerEvent
8074 //
8075 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8076 //******************************************************************************
8077 
8078 void
8079 IOPMrootDomain::dispatchPowerEvent(
8080 	uint32_t event, void * arg0, uint64_t arg1 )
8081 {
8082 	ASSERT_GATED();
8083 
8084 	switch (event) {
8085 	case kPowerEventFeatureChanged:
8086 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8087 		messageClients(kIOPMMessageFeatureChange, this);
8088 		break;
8089 
8090 	case kPowerEventReceivedPowerNotification:
8091 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8092 		handlePowerNotification((UInt32)(uintptr_t) arg0 );
8093 		break;
8094 
8095 	case kPowerEventSystemBootCompleted:
8096 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8097 		if (systemBooting) {
8098 			systemBooting = false;
8099 
8100 			if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8101 				DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8102 				if (test_sleep_in_vm && gSleepDisabledFlag) {
8103 					DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8104 					gSleepDisabledFlag = 0;
8105 				}
8106 			}
8107 
8108 			if (lowBatteryCondition || thermalEmergencyState) {
8109 				if (lowBatteryCondition) {
8110 					privateSleepSystem(kIOPMSleepReasonLowPower);
8111 				} else {
8112 					privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8113 				}
8114 				// The rest is unnecessary since the system is expected
8115 				// to sleep immediately. The following wake will update
8116 				// everything.
8117 				break;
8118 			}
8119 
8120 			sleepWakeDebugMemAlloc();
8121 			saveFailureData2File();
8122 
8123 			// If lid is closed, re-send lid closed notification
8124 			// now that booting is complete.
8125 			if (clamshellClosed) {
8126 				handlePowerNotification(kLocalEvalClamshellCommand);
8127 			}
8128 			evaluatePolicy( kStimulusAllowSystemSleepChanged );
8129 		}
8130 		break;
8131 
8132 	case kPowerEventSystemShutdown:
8133 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8134 		if (kOSBooleanTrue == (OSBoolean *) arg0) {
8135 			/* We set systemShutdown = true during shutdown
8136 			 *  to prevent sleep at unexpected times while loginwindow is trying
8137 			 *  to shutdown apps and while the OS is trying to transition to
8138 			 *  complete power of.
8139 			 *
8140 			 *  Set to true during shutdown, as soon as loginwindow shows
8141 			 *  the "shutdown countdown dialog", through individual app
8142 			 *  termination, and through black screen kernel shutdown.
8143 			 */
8144 			systemShutdown = true;
8145 		} else {
8146 			/*
8147 			 *  A shutdown was initiated, but then the shutdown
8148 			 *  was cancelled, clearing systemShutdown to false here.
8149 			 */
8150 			systemShutdown = false;
8151 		}
8152 		break;
8153 
8154 	case kPowerEventUserDisabledSleep:
8155 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8156 		userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8157 		break;
8158 
8159 	case kPowerEventRegisterSystemCapabilityClient:
8160 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8161 
8162 		// reset() handles the arg0 == nullptr case for us
8163 		systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8164 		/* intentional fall-through */
8165 		[[clang::fallthrough]];
8166 
8167 	case kPowerEventRegisterKernelCapabilityClient:
8168 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8169 		if (!_joinedCapabilityClients) {
8170 			_joinedCapabilityClients = OSSet::withCapacity(8);
8171 		}
8172 		if (arg0) {
8173 			OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8174 			if (_joinedCapabilityClients) {
8175 				_joinedCapabilityClients->setObject(notify.get());
8176 				synchronizePowerTree( kIOPMSyncNoChildNotify );
8177 			}
8178 		}
8179 		break;
8180 
8181 	case kPowerEventPolicyStimulus:
8182 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8183 		if (arg0) {
8184 			int stimulus = (int)(uintptr_t) arg0;
8185 			evaluatePolicy(stimulus, (uint32_t) arg1);
8186 		}
8187 		break;
8188 
8189 	case kPowerEventAssertionCreate:
8190 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8191 		if (pmAssertions) {
8192 			pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8193 		}
8194 		break;
8195 
8196 
8197 	case kPowerEventAssertionRelease:
8198 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8199 		if (pmAssertions) {
8200 			pmAssertions->handleReleaseAssertion(arg1);
8201 		}
8202 		break;
8203 
8204 	case kPowerEventAssertionSetLevel:
8205 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8206 		if (pmAssertions) {
8207 			pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8208 		}
8209 		break;
8210 
8211 	case kPowerEventQueueSleepWakeUUID:
8212 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8213 		handleQueueSleepWakeUUID((OSObject *)arg0);
8214 		break;
8215 	case kPowerEventPublishSleepWakeUUID:
8216 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8217 		handlePublishSleepWakeUUID((bool)arg0);
8218 		break;
8219 
8220 	case kPowerEventSetDisplayPowerOn:
8221 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8222 		if (arg1 != 0) {
8223 			displayPowerOnRequested = true;
8224 		} else {
8225 			displayPowerOnRequested = false;
8226 		}
8227 		handleSetDisplayPowerOn(displayPowerOnRequested);
8228 		break;
8229 
8230 	case kPowerEventPublishWakeType:
8231 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8232 
8233 		// Don't replace wake type property if already set
8234 		if ((arg0 == gIOPMWakeTypeUserKey) ||
8235 		    !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8236 			const char * wakeType = NULL;
8237 
8238 			if (arg0 == gIOPMWakeTypeUserKey) {
8239 				requestUserActive(this, "WakeTypeUser");
8240 				wakeType = kIOPMRootDomainWakeTypeUser;
8241 			} else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8242 				if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8243 					requestUserActive(this, "WakeTypeAlarm");
8244 				}
8245 				wakeType = kIOPMRootDomainWakeTypeAlarm;
8246 			} else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8247 				darkWakeSleepService = true;
8248 				wakeType = kIOPMRootDomainWakeTypeSleepService;
8249 			} else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8250 				wakeType = kIOPMRootDomainWakeTypeMaintenance;
8251 			}
8252 
8253 			if (wakeType) {
8254 				setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8255 			}
8256 		}
8257 		break;
8258 
8259 	case kPowerEventAOTEvaluate:
8260 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8261 		if (_aotReadyToFullWake) {
8262 			aotEvaluate(NULL);
8263 		}
8264 		break;
8265 	}
8266 }
8267 
8268 //******************************************************************************
8269 // systemPowerEventOccurred
8270 //
8271 // The power controller is notifying us of a hardware-related power management
8272 // event that we must handle.
8273 //
8274 // systemPowerEventOccurred covers the same functionality that
8275 // receivePowerNotification does; it simply provides a richer API for conveying
8276 // more information.
8277 //******************************************************************************
8278 
8279 IOReturn
8280 IOPMrootDomain::systemPowerEventOccurred(
8281 	const OSSymbol *event,
8282 	uint32_t intValue)
8283 {
8284 	IOReturn        attempt = kIOReturnSuccess;
8285 	OSSharedPtr<OSNumber>        newNumber;
8286 
8287 	if (!event) {
8288 		return kIOReturnBadArgument;
8289 	}
8290 
8291 	newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8292 	if (!newNumber) {
8293 		return kIOReturnInternalError;
8294 	}
8295 
8296 	attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8297 
8298 	return attempt;
8299 }
8300 
8301 void
8302 IOPMrootDomain::setThermalState(OSObject *value)
8303 {
8304 	OSNumber * num;
8305 
8306 	if (gIOPMWorkLoop->inGate() == false) {
8307 		gIOPMWorkLoop->runAction(
8308 			OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8309 			(OSObject *)this,
8310 			(void *)value);
8311 
8312 		return;
8313 	}
8314 	if (value && (num = OSDynamicCast(OSNumber, value))) {
8315 		thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8316 		    (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8317 	}
8318 }
8319 
8320 IOReturn
8321 IOPMrootDomain::systemPowerEventOccurred(
8322 	const OSSymbol *event,
8323 	OSObject *value)
8324 {
8325 	OSSharedPtr<OSDictionary> thermalsDict;
8326 	bool shouldUpdate = true;
8327 
8328 	if (!event || !value) {
8329 		return kIOReturnBadArgument;
8330 	}
8331 
8332 	// LOCK
8333 	// We reuse featuresDict Lock because it already exists and guards
8334 	// the very infrequently used publish/remove feature mechanism; so there's zero rsk
8335 	// of stepping on that lock.
8336 	if (featuresDictLock) {
8337 		IOLockLock(featuresDictLock);
8338 	}
8339 
8340 	OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8341 	OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8342 
8343 	if (origThermalsDict) {
8344 		thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8345 	} else {
8346 		thermalsDict = OSDictionary::withCapacity(1);
8347 	}
8348 
8349 	if (!thermalsDict) {
8350 		shouldUpdate = false;
8351 		goto exit;
8352 	}
8353 
8354 	thermalsDict->setObject(event, value);
8355 
8356 	setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8357 
8358 exit:
8359 	// UNLOCK
8360 	if (featuresDictLock) {
8361 		IOLockUnlock(featuresDictLock);
8362 	}
8363 
8364 	if (shouldUpdate) {
8365 		if (event &&
8366 		    event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8367 			setThermalState(value);
8368 		}
8369 		messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8370 	}
8371 
8372 	return kIOReturnSuccess;
8373 }
8374 
8375 //******************************************************************************
8376 // receivePowerNotification
8377 //
8378 // The power controller is notifying us of a hardware-related power management
8379 // event that we must handle. This may be a result of an 'environment' interrupt
8380 // from the power mgt micro.
8381 //******************************************************************************
8382 
8383 IOReturn
8384 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8385 {
8386 	if (msg & kIOPMPowerButton) {
8387 		uint32_t currentPhase = pmTracer->getTracePhase();
8388 		if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8389 			DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8390 			swd_flags |= SWD_PWR_BTN_STACKSHOT;
8391 			thread_call_enter(powerButtonDown);
8392 		} else {
8393 			DEBUG_LOG("power button pressed when system is up\n");
8394 		}
8395 	} else if (msg & kIOPMPowerButtonUp) {
8396 		if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8397 			swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8398 			thread_call_enter(powerButtonUp);
8399 		}
8400 	} else {
8401 		pmPowerStateQueue->submitPowerEvent(
8402 			kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8403 	}
8404 	return kIOReturnSuccess;
8405 }
8406 
8407 void
8408 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8409 {
8410 	bool        eval_clamshell = false;
8411 	bool        eval_clamshell_alarm = false;
8412 
8413 	ASSERT_GATED();
8414 
8415 	/*
8416 	 * Local (IOPMrootDomain only) eval clamshell command
8417 	 */
8418 	if (msg & kLocalEvalClamshellCommand) {
8419 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8420 			eval_clamshell_alarm = true;
8421 
8422 			// reset isRTCAlarmWake. This evaluation should happen only once
8423 			// on RTC/Alarm wake. Any clamshell events after wake should follow
8424 			// the regular evaluation
8425 			isRTCAlarmWake = false;
8426 		} else {
8427 			eval_clamshell = true;
8428 		}
8429 	}
8430 
8431 	/*
8432 	 * Overtemp
8433 	 */
8434 	if (msg & kIOPMOverTemp) {
8435 		DLOG("Thermal overtemp message received!\n");
8436 		thermalEmergencyState = true;
8437 		privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8438 	}
8439 
8440 	/*
8441 	 * Forward DW thermal notification to client, if system is not going to sleep
8442 	 */
8443 	if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8444 		DLOG("DarkWake thermal limits message received!\n");
8445 		messageClients(kIOPMMessageDarkWakeThermalEmergency);
8446 	}
8447 
8448 	/*
8449 	 * Sleep Now!
8450 	 */
8451 	if (msg & kIOPMSleepNow) {
8452 		privateSleepSystem(kIOPMSleepReasonSoftware);
8453 	}
8454 
8455 	/*
8456 	 * Power Emergency
8457 	 */
8458 	if (msg & kIOPMPowerEmergency) {
8459 		DLOG("Received kIOPMPowerEmergency");
8460 #if HIBERNATION && defined(__arm64__)
8461 		if (!ml_is_secure_hib_supported()) {
8462 			// Wait for the next low battery notification if the system state is
8463 			// in transition.
8464 			if ((_systemTransitionType == kSystemTransitionNone) &&
8465 			    CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8466 			    !systemBooting && !systemShutdown && !gWillShutdown) {
8467 				// Setting lowBatteryCondition will prevent system sleep
8468 				lowBatteryCondition = true;
8469 
8470 				// Notify userspace to initiate system shutdown
8471 				messageClients(kIOPMMessageRequestSystemShutdown);
8472 			}
8473 		} else {
8474 			lowBatteryCondition = true;
8475 			privateSleepSystem(kIOPMSleepReasonLowPower);
8476 		}
8477 #else  /* HIBERNATION && defined(__arm64__) */
8478 		lowBatteryCondition = true;
8479 		privateSleepSystem(kIOPMSleepReasonLowPower);
8480 #endif /* HIBERNATION && defined(__arm64__) */
8481 	}
8482 
8483 	/*
8484 	 * Clamshell OPEN
8485 	 */
8486 	if (msg & kIOPMClamshellOpened) {
8487 		DLOG("Clamshell opened\n");
8488 		// Received clamshel open message from clamshell controlling driver
8489 		// Update our internal state and tell general interest clients
8490 		clamshellClosed = false;
8491 		clamshellExists = true;
8492 
8493 		// Don't issue a hid tickle when lid is open and polled on wake
8494 		if (msg & kIOPMSetValue) {
8495 			setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8496 			reportUserInput();
8497 		}
8498 
8499 		// Tell PMCPU
8500 		informCPUStateChange(kInformLid, 0);
8501 
8502 		// Tell general interest clients
8503 		sendClientClamshellNotification();
8504 
8505 		bool aborting =  ((lastSleepReason == kIOPMSleepReasonClamshell)
8506 		    || (lastSleepReason == kIOPMSleepReasonIdle)
8507 		    || (lastSleepReason == kIOPMSleepReasonMaintenance));
8508 		if (aborting) {
8509 			userActivityCount++;
8510 		}
8511 		DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8512 	}
8513 
8514 	/*
8515 	 * Clamshell CLOSED
8516 	 * Send the clamshell interest notification since the lid is closing.
8517 	 */
8518 	if (msg & kIOPMClamshellClosed) {
8519 		if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8520 		    clamshellClosed && clamshellExists) {
8521 			DLOG("Ignoring redundant Clamshell close event\n");
8522 		} else {
8523 			DLOG("Clamshell closed\n");
8524 			// Received clamshel open message from clamshell controlling driver
8525 			// Update our internal state and tell general interest clients
8526 			clamshellClosed = true;
8527 			clamshellExists = true;
8528 
8529 			// Ignore all following clamshell close events until the clamshell
8530 			// is opened or the system sleeps. When a clamshell close triggers
8531 			// a system wake, the lid driver may send us two clamshell close
8532 			// events, one for the clamshell close event itself, and a second
8533 			// close event when the driver polls the lid state on wake.
8534 			clamshellIgnoreClose = true;
8535 
8536 			// Tell PMCPU
8537 			informCPUStateChange(kInformLid, 1);
8538 
8539 			// Tell general interest clients
8540 			sendClientClamshellNotification();
8541 
8542 			// And set eval_clamshell = so we can attempt
8543 			eval_clamshell = true;
8544 		}
8545 	}
8546 
8547 	/*
8548 	 * Set Desktop mode (sent from graphics)
8549 	 *
8550 	 *  -> reevaluate lid state
8551 	 */
8552 	if (msg & kIOPMSetDesktopMode) {
8553 		desktopMode = (0 != (msg & kIOPMSetValue));
8554 		msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8555 		DLOG("Desktop mode %d\n", desktopMode);
8556 
8557 		sendClientClamshellNotification();
8558 
8559 		// Re-evaluate the lid state
8560 		eval_clamshell = true;
8561 	}
8562 
8563 	/*
8564 	 * AC Adaptor connected
8565 	 *
8566 	 *  -> reevaluate lid state
8567 	 */
8568 	if (msg & kIOPMSetACAdaptorConnected) {
8569 		acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8570 		msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8571 
8572 		// Tell CPU PM
8573 		informCPUStateChange(kInformAC, !acAdaptorConnected);
8574 
8575 		// Tell BSD if AC is connected
8576 		//      0 == external power source; 1 == on battery
8577 		post_sys_powersource(acAdaptorConnected ? 0:1);
8578 
8579 		sendClientClamshellNotification();
8580 
8581 		IOUserServer::powerSourceChanged(acAdaptorConnected);
8582 
8583 		// Re-evaluate the lid state
8584 		eval_clamshell = true;
8585 
8586 		// Lack of AC may have latched a display wrangler tickle.
8587 		// This mirrors the hardware's USB wake event latch, where a latched
8588 		// USB wake event followed by an AC attach will trigger a full wake.
8589 		latchDisplayWranglerTickle( false );
8590 
8591 #if HIBERNATION
8592 		// AC presence will reset the standy timer delay adjustment.
8593 		_standbyTimerResetSeconds = 0;
8594 #endif
8595 		if (!userIsActive) {
8596 			// Reset userActivityTime when power supply is changed(rdr 13789330)
8597 			clock_get_uptime(&userActivityTime);
8598 		}
8599 	}
8600 
8601 	/*
8602 	 * Enable Clamshell (external display disappear)
8603 	 *
8604 	 *  -> reevaluate lid state
8605 	 */
8606 	if (msg & kIOPMEnableClamshell) {
8607 		DLOG("Clamshell enabled\n");
8608 
8609 		// Re-evaluate the lid state
8610 		// System should sleep on external display disappearance
8611 		// in lid closed operation.
8612 		if (true == clamshellDisabled) {
8613 			eval_clamshell = true;
8614 
8615 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8616 			// Also clear kClamshellSleepDisableInternal when graphics enables
8617 			// the clamshell during a full wake. When graphics is behaving as
8618 			// expected, this will allow clamshell close to be honored earlier
8619 			// rather than waiting for the delayed evaluation.
8620 			if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8621 			    (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8622 			    CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8623 				setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8624 
8625 				// Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8626 				// when timer expires which is harmless but useless.
8627 				thread_call_cancel(fullWakeThreadCall);
8628 			}
8629 #endif
8630 		}
8631 
8632 		clamshellDisabled = false;
8633 		sendClientClamshellNotification();
8634 	}
8635 
8636 	/*
8637 	 * Disable Clamshell (external display appeared)
8638 	 * We don't bother re-evaluating clamshell state. If the system is awake,
8639 	 * the lid is probably open.
8640 	 */
8641 	if (msg & kIOPMDisableClamshell) {
8642 		DLOG("Clamshell disabled\n");
8643 		clamshellDisabled = true;
8644 		sendClientClamshellNotification();
8645 	}
8646 
8647 	/*
8648 	 * Evaluate clamshell and SLEEP if appropriate
8649 	 */
8650 	if (eval_clamshell_alarm && clamshellClosed) {
8651 		if (shouldSleepOnRTCAlarmWake()) {
8652 			privateSleepSystem(kIOPMSleepReasonClamshell);
8653 		}
8654 	} else if (eval_clamshell && clamshellClosed) {
8655 		if (shouldSleepOnClamshellClosed()) {
8656 			privateSleepSystem(kIOPMSleepReasonClamshell);
8657 		} else {
8658 			evaluatePolicy( kStimulusDarkWakeEvaluate );
8659 		}
8660 	}
8661 
8662 	if (msg & kIOPMProModeEngaged) {
8663 		int newState = 1;
8664 		DLOG("ProModeEngaged\n");
8665 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8666 	}
8667 
8668 	if (msg & kIOPMProModeDisengaged) {
8669 		int newState = 0;
8670 		DLOG("ProModeDisengaged\n");
8671 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8672 	}
8673 }
8674 
8675 //******************************************************************************
8676 // evaluatePolicy
8677 //
8678 // Evaluate root-domain policy in response to external changes.
8679 //******************************************************************************
8680 
8681 void
8682 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8683 {
8684 	union {
8685 		struct {
8686 			int idleSleepEnabled    : 1;
8687 			int idleSleepDisabled   : 1;
8688 			int displaySleep        : 1;
8689 			int sleepDelayChanged   : 1;
8690 			int evaluateDarkWake    : 1;
8691 			int adjustPowerState    : 1;
8692 			int userBecameInactive  : 1;
8693 			int displaySleepEntry   : 1;
8694 		} bit;
8695 		uint32_t u32;
8696 	} flags;
8697 
8698 
8699 	ASSERT_GATED();
8700 	flags.u32 = 0;
8701 
8702 	switch (stimulus) {
8703 	case kStimulusDisplayWranglerSleep:
8704 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8705 		if (!wranglerPowerOff) {
8706 			// wrangler is in sleep state or lower
8707 			flags.bit.displaySleep = true;
8708 		}
8709 		if (!wranglerAsleep) {
8710 			// transition from wrangler wake to wrangler sleep
8711 			flags.bit.displaySleepEntry = true;
8712 			wranglerAsleep = true;
8713 		}
8714 		break;
8715 
8716 	case kStimulusDisplayWranglerWake:
8717 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8718 		displayIdleForDemandSleep = false;
8719 		wranglerPowerOff = false;
8720 		wranglerAsleep = false;
8721 		break;
8722 
8723 	case kStimulusEnterUserActiveState:
8724 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8725 		if (_preventUserActive) {
8726 			DLOG("user active dropped\n");
8727 			break;
8728 		}
8729 		if (!userIsActive) {
8730 			userIsActive = true;
8731 			userWasActive = true;
8732 			clock_get_uptime(&gUserActiveAbsTime);
8733 
8734 			// Stay awake after dropping demand for display power on
8735 			if (kFullWakeReasonDisplayOn == fullWakeReason) {
8736 				fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8737 				DLOG("User activity while in notification wake\n");
8738 				changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8739 			}
8740 
8741 			kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8742 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8743 			messageClients(kIOPMMessageUserIsActiveChanged);
8744 		}
8745 		flags.bit.idleSleepDisabled = true;
8746 		break;
8747 
8748 	case kStimulusLeaveUserActiveState:
8749 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8750 		if (userIsActive) {
8751 			clock_get_uptime(&gUserInactiveAbsTime);
8752 			userIsActive = false;
8753 			clock_get_uptime(&userBecameInactiveTime);
8754 			flags.bit.userBecameInactive = true;
8755 
8756 			kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8757 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8758 			messageClients(kIOPMMessageUserIsActiveChanged);
8759 		}
8760 		break;
8761 
8762 	case kStimulusAggressivenessChanged:
8763 	{
8764 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8765 		unsigned long   aggressiveValue;
8766 		uint32_t        minutesToIdleSleep  = 0;
8767 		uint32_t        minutesToDisplayDim = 0;
8768 		uint32_t        minutesDelta        = 0;
8769 
8770 		// Fetch latest display and system sleep slider values.
8771 		aggressiveValue = 0;
8772 		getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8773 		minutesToIdleSleep = (uint32_t) aggressiveValue;
8774 
8775 		aggressiveValue = 0;
8776 		getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8777 		minutesToDisplayDim = (uint32_t) aggressiveValue;
8778 		DLOG("aggressiveness changed: system %u->%u, display %u\n",
8779 		    sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8780 
8781 		DLOG("idle time -> %d ms (ena %d)\n",
8782 		    idleMilliSeconds, (minutesToIdleSleep != 0));
8783 
8784 		// How long to wait before sleeping the system once
8785 		// the displays turns off is indicated by 'extraSleepDelay'.
8786 
8787 		if (minutesToIdleSleep > minutesToDisplayDim) {
8788 			minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8789 		} else if (minutesToIdleSleep == minutesToDisplayDim) {
8790 			minutesDelta = 1;
8791 		}
8792 
8793 		if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8794 			idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8795 		}
8796 
8797 		if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8798 			flags.bit.idleSleepDisabled = true;
8799 			idleSleepEnabled = false;
8800 		}
8801 #if !defined(XNU_TARGET_OS_OSX)
8802 		if (0x7fffffff == minutesToIdleSleep) {
8803 			minutesToIdleSleep = idleMilliSeconds / 1000;
8804 		}
8805 #endif /* !defined(XNU_TARGET_OS_OSX) */
8806 
8807 		if (((minutesDelta != extraSleepDelay) ||
8808 		    (userActivityTime != userActivityTime_prev)) &&
8809 		    !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8810 			flags.bit.sleepDelayChanged = true;
8811 		}
8812 
8813 		if (systemDarkWake && !darkWakeToSleepASAP &&
8814 		    (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8815 			// Reconsider decision to remain in dark wake
8816 			flags.bit.evaluateDarkWake = true;
8817 		}
8818 
8819 		sleepSlider = minutesToIdleSleep;
8820 		extraSleepDelay = minutesDelta;
8821 		userActivityTime_prev = userActivityTime;
8822 	}   break;
8823 
8824 	case kStimulusDemandSystemSleep:
8825 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8826 		displayIdleForDemandSleep = true;
8827 		if (wrangler && wranglerIdleSettings) {
8828 			// Request wrangler idle only when demand sleep is triggered
8829 			// from full wake.
8830 			if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8831 				wrangler->setProperties(wranglerIdleSettings.get());
8832 				DLOG("Requested wrangler idle\n");
8833 			}
8834 		}
8835 		// arg = sleepReason
8836 		changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8837 		break;
8838 
8839 	case kStimulusAllowSystemSleepChanged:
8840 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8841 		flags.bit.adjustPowerState = true;
8842 		break;
8843 
8844 	case kStimulusDarkWakeActivityTickle:
8845 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8846 		// arg == true implies real and not self generated wrangler tickle.
8847 		// Update wake type on PM work loop instead of the tickle thread to
8848 		// eliminate the possibility of an early tickle clobbering the wake
8849 		// type set by the platform driver.
8850 		if (arg == true) {
8851 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8852 		}
8853 
8854 		if (!darkWakeExit) {
8855 			if (latchDisplayWranglerTickle(true)) {
8856 				DLOG("latched tickle\n");
8857 				break;
8858 			}
8859 
8860 			darkWakeExit = true;
8861 			DLOG("Requesting full wake due to dark wake activity tickle\n");
8862 			requestFullWake( kFullWakeReasonLocalUser );
8863 		}
8864 		break;
8865 
8866 	case kStimulusDarkWakeEntry:
8867 	case kStimulusDarkWakeReentry:
8868 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8869 		// Any system transitions since the last dark wake transition
8870 		// will invalid the stimulus.
8871 
8872 		if (arg == _systemStateGeneration) {
8873 			DLOG("dark wake entry\n");
8874 			systemDarkWake = true;
8875 
8876 			// Keep wranglerPowerOff an invariant when wrangler is absent
8877 			if (wrangler) {
8878 				wranglerPowerOff = true;
8879 			}
8880 
8881 			if (kStimulusDarkWakeEntry == stimulus) {
8882 				clock_get_uptime(&userBecameInactiveTime);
8883 				flags.bit.evaluateDarkWake = true;
8884 				if (activitySinceSleep()) {
8885 					DLOG("User activity recorded while going to darkwake\n");
8886 					reportUserInput();
8887 				}
8888 			}
8889 
8890 			// Always accelerate disk spindown while in dark wake,
8891 			// even if system does not support/allow sleep.
8892 
8893 			cancelIdleSleepTimer();
8894 			setQuickSpinDownTimeout();
8895 		}
8896 		break;
8897 
8898 	case kStimulusDarkWakeEvaluate:
8899 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8900 		if (systemDarkWake) {
8901 			flags.bit.evaluateDarkWake = true;
8902 		}
8903 		break;
8904 
8905 	case kStimulusNoIdleSleepPreventers:
8906 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8907 		flags.bit.adjustPowerState = true;
8908 		break;
8909 	} /* switch(stimulus) */
8910 
8911 	if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8912 		DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8913 		    darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8914 		if (darkWakeToSleepASAP ||
8915 		    (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8916 			uint32_t newSleepReason;
8917 
8918 			if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8919 				// System was previously in full wake. Sleep reason from
8920 				// full to dark already recorded in fullToDarkReason.
8921 
8922 				if (lowBatteryCondition) {
8923 					newSleepReason = kIOPMSleepReasonLowPower;
8924 				} else if (thermalEmergencyState) {
8925 					newSleepReason = kIOPMSleepReasonThermalEmergency;
8926 				} else {
8927 					newSleepReason = fullToDarkReason;
8928 				}
8929 			} else {
8930 				// In dark wake from system sleep.
8931 
8932 				if (darkWakeSleepService) {
8933 					newSleepReason = kIOPMSleepReasonSleepServiceExit;
8934 				} else {
8935 					newSleepReason = kIOPMSleepReasonMaintenance;
8936 				}
8937 			}
8938 
8939 			if (checkSystemCanSleep(newSleepReason)) {
8940 				privateSleepSystem(newSleepReason);
8941 			}
8942 		} else { // non-maintenance (network) dark wake
8943 			if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8944 				// Release power clamp, and wait for children idle.
8945 				adjustPowerState(true);
8946 			} else {
8947 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8948 			}
8949 		}
8950 	}
8951 
8952 	if (systemDarkWake) {
8953 		// The rest are irrelevant while system is in dark wake.
8954 		flags.u32 = 0;
8955 	}
8956 
8957 	if ((flags.bit.displaySleepEntry) &&
8958 	    (kFullWakeReasonDisplayOn == fullWakeReason)) {
8959 		// kIOPMSleepReasonNotificationWakeExit
8960 		DLOG("Display sleep while in notification wake\n");
8961 		changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8962 	}
8963 
8964 	if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8965 		bool cancelQuickSpindown = false;
8966 
8967 		if (flags.bit.sleepDelayChanged) {
8968 			// Cancel existing idle sleep timer and quick disk spindown.
8969 			// New settings will be applied by the idleSleepEnabled flag
8970 			// handler below if idle sleep is enabled.
8971 
8972 			DLOG("extra sleep timer changed\n");
8973 			cancelIdleSleepTimer();
8974 			cancelQuickSpindown = true;
8975 		} else {
8976 			DLOG("user inactive\n");
8977 		}
8978 
8979 		if (!userIsActive && idleSleepEnabled) {
8980 			startIdleSleepTimer(getTimeToIdleSleep());
8981 		}
8982 
8983 		if (cancelQuickSpindown) {
8984 			restoreUserSpinDownTimeout();
8985 		}
8986 	}
8987 
8988 	if (flags.bit.idleSleepEnabled) {
8989 		DLOG("idle sleep timer enabled\n");
8990 		if (!wrangler) {
8991 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8992 			startIdleSleepTimer(getTimeToIdleSleep());
8993 #else
8994 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8995 			startIdleSleepTimer( idleMilliSeconds );
8996 #endif
8997 		} else {
8998 			// Start idle timer if prefs now allow system sleep
8999 			// and user is already inactive. Disk spindown is
9000 			// accelerated upon timer expiration.
9001 
9002 			if (!userIsActive) {
9003 				startIdleSleepTimer(getTimeToIdleSleep());
9004 			}
9005 		}
9006 	}
9007 
9008 	if (flags.bit.idleSleepDisabled) {
9009 		DLOG("idle sleep timer disabled\n");
9010 		cancelIdleSleepTimer();
9011 		restoreUserSpinDownTimeout();
9012 		adjustPowerState();
9013 	}
9014 
9015 	if (flags.bit.adjustPowerState) {
9016 		bool sleepASAP = false;
9017 
9018 		if (!systemBooting && (0 == idleSleepPreventersCount())) {
9019 			if (!wrangler) {
9020 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9021 				if (idleSleepEnabled) {
9022 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9023 					if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9024 						sleepASAP = true;
9025 					}
9026 #else
9027 					// stay awake for at least idleMilliSeconds
9028 					startIdleSleepTimer(idleMilliSeconds);
9029 #endif
9030 				}
9031 			} else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9032 				sleepASAP = true;
9033 			}
9034 		}
9035 
9036 		adjustPowerState(sleepASAP);
9037 	}
9038 }
9039 
9040 //******************************************************************************
9041 
9042 unsigned int
9043 IOPMrootDomain::idleSleepPreventersCount()
9044 {
9045 	if (_aotMode) {
9046 		unsigned int count __block;
9047 		count = 0;
9048 		preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9049 		{
9050 			count += (NULL == obj->metaCast("AppleARMBacklight"));
9051 			return false;
9052 		});
9053 		return count;
9054 	}
9055 
9056 	return preventIdleSleepList->getCount();
9057 }
9058 
9059 
9060 //******************************************************************************
9061 // requestFullWake
9062 //
9063 // Request transition from dark wake to full wake
9064 //******************************************************************************
9065 
9066 void
9067 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9068 {
9069 	uint32_t        options = 0;
9070 	IOService *     pciRoot = NULL;
9071 	bool            promotion = false;
9072 
9073 	// System must be in dark wake and a valid reason for entering full wake
9074 	if ((kFullWakeReasonNone == reason) ||
9075 	    (kFullWakeReasonNone != fullWakeReason) ||
9076 	    (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9077 		return;
9078 	}
9079 
9080 	// Will clear reason upon exit from full wake
9081 	fullWakeReason = reason;
9082 
9083 	_desiredCapability |= (kIOPMSystemCapabilityGraphics |
9084 	    kIOPMSystemCapabilityAudio);
9085 
9086 	if ((kSystemTransitionWake == _systemTransitionType) &&
9087 	    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9088 	    !darkWakePowerClamped) {
9089 		// Promote to full wake while waking up to dark wake due to tickle.
9090 		// PM will hold off notifying the graphics subsystem about system wake
9091 		// as late as possible, so if a HID tickle does arrive, graphics can
9092 		// power up from this same wake transition. Otherwise, the latency to
9093 		// power up graphics on the following transition can be huge on certain
9094 		// systems. However, once any power clamping has taken effect, it is
9095 		// too late to promote the current dark wake transition to a full wake.
9096 		_pendingCapability |= (kIOPMSystemCapabilityGraphics |
9097 		    kIOPMSystemCapabilityAudio);
9098 
9099 		// Tell the PCI parent of audio and graphics drivers to stop
9100 		// delaying the child notifications. Same for root domain.
9101 		pciRoot = pciHostBridgeDriver.get();
9102 		willEnterFullWake();
9103 		promotion = true;
9104 	}
9105 
9106 	// Unsafe to cancel once graphics was powered.
9107 	// If system woke from dark wake, the return to sleep can
9108 	// be cancelled. "awake -> dark -> sleep" transition
9109 	// can be cancelled also, during the "dark -> sleep" phase
9110 	// *prior* to driver power down.
9111 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9112 	    _pendingCapability == 0) {
9113 		options |= kIOPMSyncCancelPowerDown;
9114 	}
9115 
9116 	synchronizePowerTree(options, pciRoot);
9117 
9118 	if (kFullWakeReasonLocalUser == fullWakeReason) {
9119 		// IOGraphics doesn't light the display even though graphics is
9120 		// enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9121 		// So, do an explicit activity tickle
9122 		if (wrangler) {
9123 			wrangler->activityTickle(0, 0);
9124 		}
9125 	}
9126 
9127 	// Log a timestamp for the initial full wake request.
9128 	// System may not always honor this full wake request.
9129 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9130 		AbsoluteTime    now;
9131 		uint64_t        nsec;
9132 
9133 		clock_get_uptime(&now);
9134 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9135 		absolutetime_to_nanoseconds(now, &nsec);
9136 		MSG("full wake %s (reason %u) %u ms\n",
9137 		    promotion ? "promotion" : "request",
9138 		    fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9139 	}
9140 }
9141 
9142 //******************************************************************************
9143 // willEnterFullWake
9144 //
9145 // System will enter full wake from sleep, from dark wake, or from dark
9146 // wake promotion. This function aggregate things that are in common to
9147 // all three full wake transitions.
9148 //
9149 // Assumptions: fullWakeReason was updated
9150 //******************************************************************************
9151 
9152 void
9153 IOPMrootDomain::willEnterFullWake( void )
9154 {
9155 	hibernateRetry = false;
9156 	sleepToStandby = false;
9157 	standbyNixed   = false;
9158 	resetTimers    = false;
9159 	sleepTimerMaintenance = false;
9160 
9161 	assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9162 
9163 	_systemMessageClientMask = kSystemMessageClientPowerd |
9164 	    kSystemMessageClientLegacyApp;
9165 
9166 	if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9167 		// First time to attain full wake capability since the last wake
9168 		_systemMessageClientMask |= kSystemMessageClientKernel;
9169 
9170 		// Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9171 		setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9172 		    (kFullWakeReasonLocalUser == fullWakeReason) ?
9173 		    kOSBooleanTrue : kOSBooleanFalse);
9174 	}
9175 #if HIBERNATION
9176 	IOHibernateSetWakeCapabilities(_pendingCapability);
9177 #endif
9178 
9179 	IOService::setAdvisoryTickleEnable( true );
9180 	tellClients(kIOMessageSystemWillPowerOn);
9181 	preventTransitionToUserActive(false);
9182 }
9183 
9184 //******************************************************************************
9185 // fullWakeDelayedWork
9186 //
9187 // System has already entered full wake. Invoked by a delayed thread call.
9188 //******************************************************************************
9189 
9190 void
9191 IOPMrootDomain::fullWakeDelayedWork( void )
9192 {
9193 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9194 	if (!gIOPMWorkLoop->inGate()) {
9195 		gIOPMWorkLoop->runAction(
9196 			OSMemberFunctionCast(IOWorkLoop::Action, this,
9197 			&IOPMrootDomain::fullWakeDelayedWork), this);
9198 		return;
9199 	}
9200 
9201 	DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9202 	    _currentCapability, _pendingCapability, _highestCapability,
9203 	    clamshellDisabled, clamshellSleepDisableMask);
9204 
9205 	if (clamshellExists &&
9206 	    CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9207 	    !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9208 		if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9209 			setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9210 		} else {
9211 			// Not the initial full wake after waking from sleep.
9212 			// Evaluate the clamshell for rdar://problem/9157444.
9213 			receivePowerNotification(kLocalEvalClamshellCommand);
9214 		}
9215 	}
9216 #endif
9217 }
9218 
9219 //******************************************************************************
9220 // evaluateAssertions
9221 //
9222 //******************************************************************************
9223 
9224 // Bitmask of all kernel assertions that prevent system idle sleep.
9225 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9226 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9227 	(kIOPMDriverAssertionReservedBit7 | \
9228 	 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9229 
9230 void
9231 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9232 {
9233 	IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9234 
9235 	messageClients(kIOPMMessageDriverAssertionsChanged);
9236 
9237 	if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9238 		if (wrangler) {
9239 			bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9240 
9241 			DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9242 			wrangler->setIgnoreIdleTimer( value );
9243 		}
9244 	}
9245 
9246 	if (changedBits & kIOPMDriverAssertionCPUBit) {
9247 		if (_aotNow) {
9248 			IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9249 		}
9250 		evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9251 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9252 			AbsoluteTime    now;
9253 			clock_usec_t    microsecs;
9254 			clock_get_uptime(&now);
9255 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9256 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
9257 			if (assertOnWakeReport) {
9258 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9259 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9260 			}
9261 		}
9262 	}
9263 
9264 	if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9265 		if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9266 			if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9267 				DLOG("PreventIdleSleep driver assertion raised\n");
9268 				bool ok = updatePreventIdleSleepList(this, true);
9269 				if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9270 					// Cancel idle sleep if there is one in progress
9271 					cancelIdlePowerDown(this);
9272 				}
9273 			}
9274 		} else {
9275 			DLOG("PreventIdleSleep driver assertion dropped\n");
9276 			updatePreventIdleSleepList(this, false);
9277 		}
9278 	}
9279 }
9280 
9281 // MARK: -
9282 // MARK: Statistics
9283 
9284 //******************************************************************************
9285 // pmStats
9286 //
9287 //******************************************************************************
9288 
9289 void
9290 IOPMrootDomain::pmStatsRecordEvent(
9291 	int                 eventIndex,
9292 	AbsoluteTime        timestamp)
9293 {
9294 	bool        starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9295 	bool        stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9296 	uint64_t    delta;
9297 	uint64_t    nsec;
9298 	OSSharedPtr<OSData> publishPMStats;
9299 
9300 	eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9301 
9302 	absolutetime_to_nanoseconds(timestamp, &nsec);
9303 
9304 	switch (eventIndex) {
9305 	case kIOPMStatsHibernateImageWrite:
9306 		if (starting) {
9307 			gPMStats.hibWrite.start = nsec;
9308 		} else if (stopping) {
9309 			gPMStats.hibWrite.stop = nsec;
9310 		}
9311 
9312 		if (stopping) {
9313 			delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9314 			IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9315 		}
9316 		break;
9317 	case kIOPMStatsHibernateImageRead:
9318 		if (starting) {
9319 			gPMStats.hibRead.start = nsec;
9320 		} else if (stopping) {
9321 			gPMStats.hibRead.stop = nsec;
9322 		}
9323 
9324 		if (stopping) {
9325 			delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9326 			IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9327 
9328 			publishPMStats = OSData::withValue(gPMStats);
9329 			setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9330 			bzero(&gPMStats, sizeof(gPMStats));
9331 		}
9332 		break;
9333 	}
9334 }
9335 
9336 /*
9337  * Appends a record of the application response to
9338  * IOPMrootDomain::pmStatsAppResponses
9339  */
9340 void
9341 IOPMrootDomain::pmStatsRecordApplicationResponse(
9342 	const OSSymbol      *response,
9343 	const char          *name,
9344 	int                 messageType,
9345 	uint32_t            delay_ms,
9346 	uint64_t            id,
9347 	OSObject            *object,
9348 	IOPMPowerStateIndex powerState,
9349 	bool                async)
9350 {
9351 	OSSharedPtr<OSDictionary>    responseDescription;
9352 	OSSharedPtr<OSNumber>        delayNum;
9353 	OSSharedPtr<OSNumber>        powerCaps;
9354 	OSSharedPtr<OSNumber>        pidNum;
9355 	OSSharedPtr<OSNumber>        msgNum;
9356 	OSSharedPtr<const OSSymbol>  appname;
9357 	OSSharedPtr<const OSSymbol>  sleep;
9358 	OSSharedPtr<const OSSymbol>  wake;
9359 	IOPMServiceInterestNotifier *notify = NULL;
9360 
9361 	if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9362 		if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9363 			notify->ackTimeoutCnt++;
9364 		} else {
9365 			notify->ackTimeoutCnt = 0;
9366 		}
9367 	}
9368 
9369 	if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9370 	    (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9371 		return;
9372 	}
9373 
9374 
9375 	if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9376 		kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9377 	} else if (notify) {
9378 		// User space app or kernel capability client
9379 		if (id) {
9380 			kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9381 		} else {
9382 			kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9383 		}
9384 		notify->msgType = 0;
9385 	}
9386 
9387 	responseDescription = OSDictionary::withCapacity(5);
9388 	if (responseDescription) {
9389 		if (response) {
9390 			responseDescription->setObject(_statsResponseTypeKey.get(), response);
9391 		}
9392 
9393 		msgNum = OSNumber::withNumber(messageType, 32);
9394 		if (msgNum) {
9395 			responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9396 		}
9397 
9398 		if (!name && notify && notify->identifier) {
9399 			name = notify->identifier->getCStringNoCopy();
9400 		}
9401 
9402 		if (name && (strlen(name) > 0)) {
9403 			appname = OSSymbol::withCString(name);
9404 			if (appname) {
9405 				responseDescription->setObject(_statsNameKey.get(), appname.get());
9406 			}
9407 		}
9408 
9409 		if (!id && notify) {
9410 			id = notify->uuid0;
9411 		}
9412 		pidNum = OSNumber::withNumber(id, 64);
9413 		if (pidNum) {
9414 			responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9415 		}
9416 
9417 		delayNum = OSNumber::withNumber(delay_ms, 32);
9418 		if (delayNum) {
9419 			responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9420 		}
9421 
9422 		if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9423 			powerCaps = OSNumber::withNumber(powerState, 32);
9424 
9425 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9426 			static const char * driverCallTypes[] = {
9427 				[kDriverCallInformPreChange]  = "powerStateWillChangeTo",
9428 				[kDriverCallInformPostChange] = "powerStateDidChangeTo",
9429 				[kDriverCallSetPowerState]    = "setPowerState"
9430 			};
9431 
9432 			if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9433 				DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9434 				    name, id, driverCallTypes[messageType], (uint32_t) powerState,
9435 				    async ? "async " : "", delay_ms);
9436 			}
9437 #endif
9438 		} else {
9439 			powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9440 		}
9441 		if (powerCaps) {
9442 			responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9443 		}
9444 
9445 		sleep = OSSymbol::withCString("Sleep");
9446 		wake = OSSymbol::withCString("Wake");
9447 		if (_systemTransitionType == kSystemTransitionSleep) {
9448 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9449 		} else if (_systemTransitionType == kSystemTransitionWake) {
9450 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9451 		} else if (_systemTransitionType == kSystemTransitionCapability) {
9452 			if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9453 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9454 			} else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9455 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9456 			}
9457 		}
9458 
9459 		IOLockLock(pmStatsLock);
9460 		if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9461 			pmStatsAppResponses->setObject(responseDescription.get());
9462 		}
9463 		IOLockUnlock(pmStatsLock);
9464 	}
9465 
9466 	return;
9467 }
9468 
9469 // MARK: -
9470 // MARK: PMTraceWorker
9471 
9472 //******************************************************************************
9473 // TracePoint support
9474 //
9475 //******************************************************************************
9476 
9477 #define kIOPMRegisterNVRAMTracePointHandlerKey  \
9478 	"IOPMRegisterNVRAMTracePointHandler"
9479 
9480 IOReturn
9481 IOPMrootDomain::callPlatformFunction(
9482 	const OSSymbol * functionName,
9483 	bool waitForFunction,
9484 	void * param1, void * param2,
9485 	void * param3, void * param4 )
9486 {
9487 	if (pmTracer && functionName &&
9488 	    functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9489 	    !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9490 		uint32_t    tracePointPhases, tracePointPCI;
9491 		uint64_t    statusCode;
9492 
9493 		pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9494 		pmTracer->tracePointTarget  = (void *) param2;
9495 		tracePointPCI               = (uint32_t)(uintptr_t) param3;
9496 		tracePointPhases            = (uint32_t)(uintptr_t) param4;
9497 		if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9498 			OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9499 			if (node) {
9500 				OSSharedPtr<OSObject> bootRomFailureProp;
9501 				bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9502 				OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9503 				uint32_t bootFailureCode;
9504 				if (data && data->getLength() == sizeof(bootFailureCode)) {
9505 					// Failure code from EFI/BootRom is a four byte structure
9506 					memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9507 					tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9508 				}
9509 			}
9510 		}
9511 		statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9512 		if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9513 			MSG("Sleep failure code 0x%08x 0x%08x\n",
9514 			    tracePointPCI, tracePointPhases);
9515 		}
9516 		setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9517 		pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9518 
9519 		return kIOReturnSuccess;
9520 	}
9521 #if HIBERNATION
9522 	else if (functionName &&
9523 	    functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9524 		if (gSleepPolicyHandler) {
9525 			return kIOReturnExclusiveAccess;
9526 		}
9527 		if (!param1) {
9528 			return kIOReturnBadArgument;
9529 		}
9530 		gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9531 		gSleepPolicyTarget  = (void *) param2;
9532 		setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9533 		return kIOReturnSuccess;
9534 	}
9535 #endif
9536 
9537 	return super::callPlatformFunction(
9538 		functionName, waitForFunction, param1, param2, param3, param4);
9539 }
9540 
9541 void
9542 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9543     uintptr_t param1, uintptr_t param2, uintptr_t param3)
9544 {
9545 	uint32_t code   = IODBG_POWER(event);
9546 	uint64_t regId  = id;
9547 	if (regId == 0) {
9548 		regId  = getRegistryEntryID();
9549 	}
9550 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9551 }
9552 
9553 void
9554 IOPMrootDomain::tracePoint( uint8_t point )
9555 {
9556 	if (systemBooting) {
9557 		return;
9558 	}
9559 
9560 	if (kIOPMTracePointWakeCapabilityClients == point) {
9561 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9562 	}
9563 
9564 	kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9565 	pmTracer->tracePoint(point);
9566 }
9567 
9568 static void
9569 kext_log_putc(char c)
9570 {
9571 	if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9572 		return;
9573 	}
9574 	if (c == '(' || c == '[' || c == ' ') {
9575 		c = 0;
9576 		gKextNameEnd = true;
9577 	}
9578 
9579 	gKextNameBuf[gKextNamePos++] = c;
9580 }
9581 
9582 static int
9583 kext_log(const char *fmt, ...)
9584 {
9585 	va_list listp;
9586 
9587 	va_start(listp, fmt);
9588 	_doprnt(fmt, &listp, &kext_log_putc, 16);
9589 	va_end(listp);
9590 
9591 	return 0;
9592 }
9593 
9594 static OSPtr<const OSSymbol>
9595 copyKextIdentifierWithAddress(vm_address_t address)
9596 {
9597 	OSSharedPtr<const OSSymbol> identifer;
9598 
9599 	IOLockLock(gHaltLogLock);
9600 
9601 	gKextNameEnd = false;
9602 	gKextNamePos = 0;
9603 	gKextNameBuf[0] = 0;
9604 
9605 	OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9606 	gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9607 	identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9608 
9609 	IOLockUnlock(gHaltLogLock);
9610 
9611 	return identifer;
9612 }
9613 
9614 // Caller serialized using PM workloop
9615 const char *
9616 IOPMrootDomain::getNotificationClientName(OSObject *object)
9617 {
9618 	IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9619 	const char *clientName = "UNKNOWN";
9620 
9621 	if (!notifier->clientName) {
9622 		// Check for user client
9623 		if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9624 			OSNumber *clientID = NULL;
9625 			messageClient(kIOMessageCopyClientID, object, &clientID);
9626 			if (clientID) {
9627 				OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9628 				if (string) {
9629 					notifier->clientName = OSSymbol::withString(string.get());
9630 				}
9631 				clientID->release();
9632 			}
9633 		} else if (notifier->identifier) {
9634 			notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9635 		}
9636 	}
9637 
9638 	if (notifier->clientName) {
9639 		clientName = notifier->clientName->getCStringNoCopy();
9640 	}
9641 
9642 	return clientName;
9643 }
9644 
9645 void
9646 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9647 {
9648 	IOPMServiceInterestNotifier *notifier;
9649 
9650 	if (systemBooting) {
9651 		return;
9652 	}
9653 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9654 	if (!notifier) {
9655 		return;
9656 	}
9657 
9658 	if (start) {
9659 		pmTracer->traceDetail(notifier->uuid0 >> 32);
9660 		kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9661 		    (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9662 
9663 		// Update notifier state used for response/ack logging
9664 		notifier->msgIndex = msgIndex;
9665 		notifier->msgAbsTime = timestamp;
9666 
9667 		if (msgIndex != UINT_MAX) {
9668 			DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9669 		} else {
9670 			DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9671 		}
9672 
9673 		assert(notifierObject == NULL);
9674 		notifierThread = current_thread();
9675 		notifierObject.reset(notifier, OSRetain);
9676 	} else {
9677 		uint64_t nsec;
9678 		uint32_t delayMS;
9679 
9680 		SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9681 		absolutetime_to_nanoseconds(timestamp, &nsec);
9682 		delayMS = (uint32_t)(nsec / 1000000ULL);
9683 		if (delayMS > notifier->maxMsgDelayMS) {
9684 			notifier->maxMsgDelayMS = delayMS;
9685 		}
9686 
9687 		assert(notifierObject == notifier);
9688 		notifierObject.reset();
9689 		notifierThread = NULL;
9690 	}
9691 }
9692 
9693 void
9694 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9695 {
9696 	if (systemBooting) {
9697 		return;
9698 	}
9699 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9700 	if (!notifier) {
9701 		return;
9702 	}
9703 
9704 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9705 	    (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9706 
9707 	DLOG("%s[%u] ack from %s took %d ms\n",
9708 	    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9709 	if (delay_ms > notifier->maxAckDelayMS) {
9710 		notifier->maxAckDelayMS = delay_ms;
9711 	}
9712 }
9713 
9714 void
9715 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9716 {
9717 	if (systemBooting) {
9718 		return;
9719 	}
9720 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9721 	if (!notifier) {
9722 		return;
9723 	}
9724 
9725 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9726 	    (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9727 
9728 	if (ack_time_us == 0) {
9729 		// Client work is done and ack will not be forthcoming
9730 		DLOG("%s[%u] response from %s took %d ms\n",
9731 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9732 	} else {
9733 		// Client needs more time and it must ack within ack_time_us
9734 		DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9735 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9736 	}
9737 }
9738 
9739 void
9740 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9741 {
9742 	if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9743 		return;
9744 	}
9745 	if (systemBooting) {
9746 		return;
9747 	}
9748 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9749 	if (!notifier) {
9750 		return;
9751 	}
9752 
9753 	DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9754 }
9755 
9756 void
9757 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9758 {
9759 	if (!systemBooting) {
9760 		uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9761 		pmTracer->traceDetail( detail );
9762 		kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9763 		DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9764 	}
9765 }
9766 
9767 void
9768 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9769 {
9770 	size_t      reportSize;
9771 	void        **report = NULL;
9772 	uint32_t    bktCnt;
9773 	uint32_t    bktSize;
9774 	uint32_t    *clientCnt;
9775 
9776 	ASSERT_GATED();
9777 
9778 	report = NULL;
9779 	if (channel_id == kAssertDelayChID) {
9780 		report = &assertOnWakeReport;
9781 		bktCnt = kAssertDelayBcktCnt;
9782 		bktSize = kAssertDelayBcktSize;
9783 		clientCnt = &assertOnWakeClientCnt;
9784 	} else if (channel_id == kSleepDelaysChID) {
9785 		report = &sleepDelaysReport;
9786 		bktCnt = kSleepDelaysBcktCnt;
9787 		bktSize = kSleepDelaysBcktSize;
9788 		clientCnt = &sleepDelaysClientCnt;
9789 	} else {
9790 		assert(false);
9791 		return;
9792 	}
9793 
9794 	switch (action) {
9795 	case kIOReportEnable:
9796 
9797 		if (*report) {
9798 			(*clientCnt)++;
9799 			break;
9800 		}
9801 
9802 		reportSize = HISTREPORT_BUFSIZE(bktCnt);
9803 		*report = IOMallocZeroData(reportSize);
9804 		if (*report == NULL) {
9805 			break;
9806 		}
9807 		HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9808 		    getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9809 
9810 		if (channel_id == kAssertDelayChID) {
9811 			assertOnWakeSecs = 0;
9812 		}
9813 
9814 		break;
9815 
9816 	case kIOReportDisable:
9817 		if (*clientCnt == 0) {
9818 			break;
9819 		}
9820 		if (*clientCnt == 1) {
9821 			IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9822 			*report = NULL;
9823 		}
9824 		(*clientCnt)--;
9825 
9826 		if (channel_id == kAssertDelayChID) {
9827 			assertOnWakeSecs = -1; // Invalid value to prevent updates
9828 		}
9829 		break;
9830 
9831 	case kIOReportGetDimensions:
9832 		if (*report) {
9833 			HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9834 		}
9835 		break;
9836 	}
9837 
9838 	return;
9839 }
9840 
9841 IOReturn
9842 IOPMrootDomain::configureReport(IOReportChannelList    *channelList,
9843     IOReportConfigureAction action,
9844     void                   *result,
9845     void                   *destination)
9846 {
9847 	unsigned cnt;
9848 	uint64_t configAction = (uint64_t)action;
9849 
9850 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9851 		if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9852 		    (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9853 		    (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9854 			if (action != kIOReportGetDimensions) {
9855 				continue;
9856 			}
9857 			SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9858 		} else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9859 		    (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9860 			gIOPMWorkLoop->runAction(
9861 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9862 				(OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9863 				(void *)configAction, (void *)result);
9864 		}
9865 	}
9866 
9867 	return super::configureReport(channelList, action, result, destination);
9868 }
9869 
9870 IOReturn
9871 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9872 {
9873 	uint32_t    size2cpy;
9874 	void        *data2cpy;
9875 	void        **report;
9876 
9877 	ASSERT_GATED();
9878 
9879 	report = NULL;
9880 	if (ch_id == kAssertDelayChID) {
9881 		report = &assertOnWakeReport;
9882 	} else if (ch_id == kSleepDelaysChID) {
9883 		report = &sleepDelaysReport;
9884 	} else {
9885 		assert(false);
9886 		return kIOReturnBadArgument;
9887 	}
9888 
9889 	if (*report == NULL) {
9890 		return kIOReturnNotOpen;
9891 	}
9892 
9893 	HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9894 	if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9895 		return kIOReturnOverrun;
9896 	}
9897 
9898 	HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9899 	dest->appendBytes(data2cpy, size2cpy);
9900 
9901 	return kIOReturnSuccess;
9902 }
9903 
9904 IOReturn
9905 IOPMrootDomain::updateReport(IOReportChannelList      *channelList,
9906     IOReportUpdateAction      action,
9907     void                     *result,
9908     void                     *destination)
9909 {
9910 	uint32_t size2cpy;
9911 	void *data2cpy;
9912 	uint8_t buf[SIMPLEREPORT_BUFSIZE];
9913 	IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9914 	unsigned cnt;
9915 	uint64_t ch_id;
9916 
9917 	if (action != kIOReportCopyChannelData) {
9918 		goto exit;
9919 	}
9920 
9921 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9922 		ch_id = channelList->channels[cnt].channel_id;
9923 
9924 		if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9925 			gIOPMWorkLoop->runAction(
9926 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9927 				(OSObject *)this, (void *)ch_id,
9928 				(void *)result, (void *)dest);
9929 			continue;
9930 		} else if ((ch_id == kSleepCntChID) ||
9931 		    (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9932 			SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9933 		} else {
9934 			continue;
9935 		}
9936 
9937 		if (ch_id == kSleepCntChID) {
9938 			SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9939 		} else if (ch_id == kDarkWkCntChID) {
9940 			SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9941 		} else if (ch_id == kUserWkCntChID) {
9942 			SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9943 		}
9944 
9945 		SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9946 		SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9947 		dest->appendBytes(data2cpy, size2cpy);
9948 	}
9949 
9950 exit:
9951 	return super::updateReport(channelList, action, result, destination);
9952 }
9953 
9954 
9955 //******************************************************************************
9956 // PMTraceWorker Class
9957 //
9958 //******************************************************************************
9959 
9960 #undef super
9961 #define super OSObject
9962 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9963 
9964 #define kPMBestGuessPCIDevicesCount     25
9965 #define kPMMaxRTCBitfieldSize           32
9966 
9967 OSPtr<PMTraceWorker>
9968 PMTraceWorker::tracer(IOPMrootDomain * owner)
9969 {
9970 	OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9971 	if (!me || !me->init()) {
9972 		return NULL;
9973 	}
9974 
9975 	DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9976 
9977 	// Note that we cannot instantiate the PCI device -> bit mappings here, since
9978 	// the IODeviceTree has not yet been created by IOPlatformExpert. We create
9979 	// this dictionary lazily.
9980 	me->owner = owner;
9981 	me->pciDeviceBitMappings = NULL;
9982 	me->pmTraceWorkerLock = IOLockAlloc();
9983 	me->tracePhase = kIOPMTracePointSystemUp;
9984 	me->traceData32 = 0;
9985 	me->loginWindowData = 0;
9986 	me->coreDisplayData = 0;
9987 	me->coreGraphicsData = 0;
9988 	return me;
9989 }
9990 
9991 void
9992 PMTraceWorker::RTC_TRACE(void)
9993 {
9994 	if (tracePointHandler && tracePointTarget) {
9995 		uint32_t    wordA;
9996 
9997 		IOLockLock(pmTraceWorkerLock);
9998 		wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9999 		    (coreGraphicsData << 8) | tracePhase;
10000 		IOLockUnlock(pmTraceWorkerLock);
10001 
10002 		tracePointHandler( tracePointTarget, traceData32, wordA );
10003 		_LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10004 	}
10005 #if DEVELOPMENT || DEBUG
10006 	if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10007 		DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10008 		IOLock *l = IOLockAlloc();
10009 		IOLockLock(l);
10010 		IOLockLock(l);
10011 	}
10012 #endif /* DEVELOPMENT || DEBUG */
10013 }
10014 
10015 int
10016 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10017 {
10018 	OSSharedPtr<const OSSymbol>    deviceName;
10019 	int                 index = -1;
10020 
10021 	IOLockLock(pmTraceWorkerLock);
10022 
10023 	if (!pciDeviceBitMappings) {
10024 		pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10025 		if (!pciDeviceBitMappings) {
10026 			goto exit;
10027 		}
10028 	}
10029 
10030 	// Check for bitmask overflow.
10031 	if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10032 		goto exit;
10033 	}
10034 
10035 	if ((deviceName = pciDevice->copyName()) &&
10036 	    (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10037 	    pciDeviceBitMappings->setObject(deviceName.get())) {
10038 		index = pciDeviceBitMappings->getCount() - 1;
10039 		_LOG("PMTrace PCI array: set object %s => %d\n",
10040 		    deviceName->getCStringNoCopy(), index);
10041 	}
10042 
10043 	if (!addedToRegistry && (index >= 0)) {
10044 		addedToRegistry = owner->setProperty("PCITopLevel", this);
10045 	}
10046 
10047 exit:
10048 	IOLockUnlock(pmTraceWorkerLock);
10049 	return index;
10050 }
10051 
10052 bool
10053 PMTraceWorker::serialize(OSSerialize *s) const
10054 {
10055 	bool ok = false;
10056 	if (pciDeviceBitMappings) {
10057 		IOLockLock(pmTraceWorkerLock);
10058 		ok = pciDeviceBitMappings->serialize(s);
10059 		IOLockUnlock(pmTraceWorkerLock);
10060 	}
10061 	return ok;
10062 }
10063 
10064 void
10065 PMTraceWorker::tracePoint(uint8_t phase)
10066 {
10067 	// clear trace detail when phase begins
10068 	if (tracePhase != phase) {
10069 		traceData32 = 0;
10070 	}
10071 
10072 	tracePhase = phase;
10073 
10074 	DLOG("trace point 0x%02x\n", tracePhase);
10075 	RTC_TRACE();
10076 }
10077 
10078 void
10079 PMTraceWorker::traceDetail(uint32_t detail)
10080 {
10081 	if (detail == traceData32) {
10082 		return;
10083 	}
10084 	traceData32 = detail;
10085 	RTC_TRACE();
10086 }
10087 
10088 void
10089 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10090 {
10091 	switch (component) {
10092 	case kIOPMLoginWindowProgress:
10093 		loginWindowData = data & kIOPMLoginWindowProgressMask;
10094 		break;
10095 	case kIOPMCoreDisplayProgress:
10096 		coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10097 		break;
10098 	case kIOPMCoreGraphicsProgress:
10099 		coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10100 		break;
10101 	default:
10102 		return;
10103 	}
10104 
10105 	DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10106 	RTC_TRACE();
10107 }
10108 
10109 void
10110 PMTraceWorker::tracePCIPowerChange(
10111 	change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10112 {
10113 	uint32_t    bitMask;
10114 	uint32_t    expectedFlag;
10115 
10116 	// Ignore PCI changes outside of system sleep/wake.
10117 	if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10118 	    (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10119 		return;
10120 	}
10121 
10122 	// Only record the WillChange transition when going to sleep,
10123 	// and the DidChange on the way up.
10124 	changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10125 	expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10126 	    kIOPMDomainWillChange : kIOPMDomainDidChange;
10127 	if (changeFlags != expectedFlag) {
10128 		return;
10129 	}
10130 
10131 	// Mark this device off in our bitfield
10132 	if (bitNum < kPMMaxRTCBitfieldSize) {
10133 		bitMask = (1 << bitNum);
10134 
10135 		if (kPowerChangeStart == type) {
10136 			traceData32 |= bitMask;
10137 			_LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n",
10138 			    service->getName(), bitNum, bitMask, traceData32);
10139 			owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10140 		} else {
10141 			traceData32 &= ~bitMask;
10142 			_LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10143 			    service->getName(), bitNum, bitMask, traceData32);
10144 			owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10145 		}
10146 
10147 		DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10148 		RTC_TRACE();
10149 	}
10150 }
10151 
10152 uint64_t
10153 PMTraceWorker::getPMStatusCode()
10154 {
10155 	return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10156 }
10157 
10158 uint8_t
10159 PMTraceWorker::getTracePhase()
10160 {
10161 	return tracePhase;
10162 }
10163 
10164 uint32_t
10165 PMTraceWorker::getTraceData()
10166 {
10167 	return traceData32;
10168 }
10169 
10170 // MARK: -
10171 // MARK: PMHaltWorker
10172 
10173 //******************************************************************************
10174 // PMHaltWorker Class
10175 //
10176 //******************************************************************************
10177 
10178 PMHaltWorker *
10179 PMHaltWorker::worker( void )
10180 {
10181 	PMHaltWorker *  me;
10182 	IOThread        thread;
10183 
10184 	do {
10185 		me = OSTypeAlloc( PMHaltWorker );
10186 		if (!me || !me->init()) {
10187 			break;
10188 		}
10189 
10190 		me->lock = IOLockAlloc();
10191 		if (!me->lock) {
10192 			break;
10193 		}
10194 
10195 		DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10196 		me->retain(); // thread holds extra retain
10197 		if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10198 			me->release();
10199 			break;
10200 		}
10201 		thread_deallocate(thread);
10202 		return me;
10203 	} while (false);
10204 
10205 	if (me) {
10206 		me->release();
10207 	}
10208 	return NULL;
10209 }
10210 
10211 void
10212 PMHaltWorker::free( void )
10213 {
10214 	DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10215 	if (lock) {
10216 		IOLockFree(lock);
10217 		lock = NULL;
10218 	}
10219 	return OSObject::free();
10220 }
10221 
10222 void
10223 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10224 {
10225 	PMHaltWorker * me = (PMHaltWorker *) arg;
10226 
10227 	IOLockLock( gPMHaltLock );
10228 	gPMHaltBusyCount++;
10229 	me->depth = gPMHaltDepth;
10230 	IOLockUnlock( gPMHaltLock );
10231 
10232 	while (me->depth >= 0) {
10233 		PMHaltWorker::work( me );
10234 
10235 		IOLockLock( gPMHaltLock );
10236 		if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10237 			// This is the last thread to finish work on this level,
10238 			// inform everyone to start working on next lower level.
10239 			gPMHaltDepth--;
10240 			me->depth = gPMHaltDepth;
10241 			gPMHaltIdleCount = 0;
10242 			thread_wakeup((event_t) &gPMHaltIdleCount);
10243 		} else {
10244 			// One or more threads are still working on this level,
10245 			// this thread must wait.
10246 			me->depth = gPMHaltDepth - 1;
10247 			do {
10248 				IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10249 			} while (me->depth != gPMHaltDepth);
10250 		}
10251 		IOLockUnlock( gPMHaltLock );
10252 	}
10253 
10254 	// No more work to do, terminate thread
10255 	DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10256 	thread_wakeup( &gPMHaltDepth );
10257 	me->release();
10258 }
10259 
10260 void
10261 PMHaltWorker::work( PMHaltWorker * me )
10262 {
10263 	OSSharedPtr<IOService>     service;
10264 	OSSet *         inner;
10265 	AbsoluteTime    startTime, elapsedTime;
10266 	UInt32          deltaTime;
10267 	bool            timeout;
10268 
10269 	while (true) {
10270 		timeout = false;
10271 
10272 		// Claim an unit of work from the shared pool
10273 		IOLockLock( gPMHaltLock );
10274 		inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10275 		if (inner) {
10276 			service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10277 			if (service) {
10278 				inner->removeObject(service.get());
10279 			}
10280 		}
10281 		IOLockUnlock( gPMHaltLock );
10282 		if (!service) {
10283 			break; // no more work at this depth
10284 		}
10285 		clock_get_uptime(&startTime);
10286 
10287 		if (!service->isInactive() &&
10288 		    service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10289 			IOLockLock(me->lock);
10290 			me->startTime = startTime;
10291 			me->service   = service.get();
10292 			me->timeout   = false;
10293 			IOLockUnlock(me->lock);
10294 
10295 			service->systemWillShutdown( gPMHaltMessageType);
10296 
10297 			// Wait for driver acknowledgement
10298 			IOLockLock(me->lock);
10299 			while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10300 				IOLockSleep(me->lock, me, THREAD_UNINT);
10301 			}
10302 			me->service = NULL;
10303 			timeout = me->timeout;
10304 			IOLockUnlock(me->lock);
10305 		}
10306 
10307 		deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10308 		if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10309 			LOG("%s driver %s (0x%llx) took %u ms\n",
10310 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10311 			    "PowerOff" : "Restart",
10312 			    service->getName(), service->getRegistryEntryID(),
10313 			    (uint32_t) deltaTime );
10314 			halt_log_enter("PowerOff/Restart handler completed",
10315 			    OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10316 			    elapsedTime);
10317 		}
10318 
10319 		me->visits++;
10320 	}
10321 }
10322 
10323 void
10324 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10325 {
10326 	UInt64          nano;
10327 	AbsoluteTime    startTime;
10328 	AbsoluteTime    endTime;
10329 
10330 	endTime = *now;
10331 
10332 	IOLockLock(me->lock);
10333 	if (me->service && !me->timeout) {
10334 		startTime = me->startTime;
10335 		nano = 0;
10336 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10337 			SUB_ABSOLUTETIME(&endTime, &startTime);
10338 			absolutetime_to_nanoseconds(endTime, &nano);
10339 		}
10340 		if (nano > 3000000000ULL) {
10341 			me->timeout = true;
10342 
10343 			halt_log_enter("PowerOff/Restart still waiting on handler",
10344 			    OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10345 			    endTime);
10346 			MSG("%s still waiting on %s\n",
10347 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?  "PowerOff" : "Restart",
10348 			    me->service->getName());
10349 		}
10350 	}
10351 	IOLockUnlock(me->lock);
10352 }
10353 
10354 //******************************************************************************
10355 // acknowledgeSystemWillShutdown
10356 //
10357 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10358 //******************************************************************************
10359 
10360 void
10361 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10362 {
10363 	PMHaltWorker            * worker;
10364 	OSSharedPtr<OSObject>     prop;
10365 
10366 	if (!from) {
10367 		return;
10368 	}
10369 
10370 	//DLOG("%s acknowledged\n", from->getName());
10371 	prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10372 	if (prop) {
10373 		worker = (PMHaltWorker *) prop.get();
10374 		IOLockLock(worker->lock);
10375 		from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10376 		thread_wakeup((event_t) worker);
10377 		IOLockUnlock(worker->lock);
10378 	} else {
10379 		DLOG("%s acknowledged without worker property\n",
10380 		    from->getName());
10381 	}
10382 }
10383 
10384 
10385 //******************************************************************************
10386 // notifySystemShutdown
10387 //
10388 // Notify all objects in PM tree that system will shutdown or restart
10389 //******************************************************************************
10390 
10391 static void
10392 notifySystemShutdown( IOService * root, uint32_t messageType )
10393 {
10394 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10395 	OSSharedPtr<IORegistryIterator>  iter;
10396 	IORegistryEntry *                entry;
10397 	IOService *                      node;
10398 	OSSet *                          inner;
10399 	OSSharedPtr<OSSet>               newInner;
10400 	PMHaltWorker *                   workers[kPMHaltMaxWorkers];
10401 	AbsoluteTime                     deadline;
10402 	unsigned int                     totalNodes = 0;
10403 	unsigned int                     depth;
10404 	unsigned int                     rootDepth;
10405 	unsigned int                     numWorkers;
10406 	unsigned int                     count;
10407 	int                              waitResult;
10408 	void *                           baseFunc;
10409 	bool                             ok;
10410 
10411 	DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10412 
10413 	baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10414 
10415 	// Iterate the entire PM tree starting from root
10416 
10417 	rootDepth = root->getDepth( gIOPowerPlane );
10418 	if (!rootDepth) {
10419 		goto done;
10420 	}
10421 
10422 	// debug - for repeated test runs
10423 	while (PMHaltWorker::metaClass->getInstanceCount()) {
10424 		IOSleep(1);
10425 	}
10426 
10427 	if (!gPMHaltArray) {
10428 		gPMHaltArray = OSArray::withCapacity(40);
10429 		if (!gPMHaltArray) {
10430 			goto done;
10431 		}
10432 	} else { // debug
10433 		gPMHaltArray->flushCollection();
10434 	}
10435 
10436 	if (!gPMHaltLock) {
10437 		gPMHaltLock = IOLockAlloc();
10438 		if (!gPMHaltLock) {
10439 			goto done;
10440 		}
10441 	}
10442 
10443 	if (!gPMHaltClientAcknowledgeKey) {
10444 		gPMHaltClientAcknowledgeKey =
10445 		    OSSymbol::withCStringNoCopy("PMShutdown");
10446 		if (!gPMHaltClientAcknowledgeKey) {
10447 			goto done;
10448 		}
10449 	}
10450 
10451 	gPMHaltMessageType = messageType;
10452 
10453 	// Depth-first walk of PM plane
10454 
10455 	iter = IORegistryIterator::iterateOver(
10456 		root, gIOPowerPlane, kIORegistryIterateRecursively);
10457 
10458 	if (iter) {
10459 		while ((entry = iter->getNextObject())) {
10460 			node = OSDynamicCast(IOService, entry);
10461 			if (!node) {
10462 				continue;
10463 			}
10464 
10465 			if (baseFunc ==
10466 			    OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10467 				continue;
10468 			}
10469 
10470 			depth = node->getDepth( gIOPowerPlane );
10471 			if (depth <= rootDepth) {
10472 				continue;
10473 			}
10474 
10475 			ok = false;
10476 
10477 			// adjust to zero based depth
10478 			depth -= (rootDepth + 1);
10479 
10480 			// gPMHaltArray is an array of containers, each container
10481 			// refers to nodes with the same depth.
10482 
10483 			count = gPMHaltArray->getCount();
10484 			while (depth >= count) {
10485 				// expand array and insert placeholders
10486 				gPMHaltArray->setObject(PLACEHOLDER);
10487 				count++;
10488 			}
10489 			count = gPMHaltArray->getCount();
10490 			if (depth < count) {
10491 				inner = (OSSet *)gPMHaltArray->getObject(depth);
10492 				if (inner == PLACEHOLDER) {
10493 					newInner = OSSet::withCapacity(40);
10494 					if (newInner) {
10495 						gPMHaltArray->replaceObject(depth, newInner.get());
10496 						inner = newInner.get();
10497 					}
10498 				}
10499 
10500 				// PM nodes that appear more than once in the tree will have
10501 				// the same depth, OSSet will refuse to add the node twice.
10502 				if (inner) {
10503 					ok = inner->setObject(node);
10504 				}
10505 			}
10506 			if (!ok) {
10507 				DLOG("Skipped PM node %s\n", node->getName());
10508 			}
10509 		}
10510 	}
10511 
10512 	// debug only
10513 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10514 		count = 0;
10515 		if (inner != PLACEHOLDER) {
10516 			count = inner->getCount();
10517 		}
10518 		DLOG("Nodes at depth %u = %u\n", i, count);
10519 	}
10520 
10521 	// strip placeholders (not all depths are populated)
10522 	numWorkers = 0;
10523 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10524 		if (inner == PLACEHOLDER) {
10525 			gPMHaltArray->removeObject(i);
10526 			continue;
10527 		}
10528 		count = inner->getCount();
10529 		if (count > numWorkers) {
10530 			numWorkers = count;
10531 		}
10532 		totalNodes += count;
10533 		i++;
10534 	}
10535 
10536 	if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10537 		goto done;
10538 	}
10539 
10540 	gPMHaltBusyCount = 0;
10541 	gPMHaltIdleCount = 0;
10542 	gPMHaltDepth = gPMHaltArray->getCount() - 1;
10543 
10544 	// Create multiple workers (and threads)
10545 
10546 	if (numWorkers > kPMHaltMaxWorkers) {
10547 		numWorkers = kPMHaltMaxWorkers;
10548 	}
10549 
10550 	DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10551 	    totalNodes, gPMHaltArray->getCount(), numWorkers);
10552 
10553 	for (unsigned int i = 0; i < numWorkers; i++) {
10554 		workers[i] = PMHaltWorker::worker();
10555 	}
10556 
10557 	// Wait for workers to exhaust all available work
10558 
10559 	IOLockLock(gPMHaltLock);
10560 	while (gPMHaltDepth >= 0) {
10561 		clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10562 
10563 		waitResult = IOLockSleepDeadline(
10564 			gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10565 		if (THREAD_TIMED_OUT == waitResult) {
10566 			AbsoluteTime now;
10567 			clock_get_uptime(&now);
10568 
10569 			IOLockUnlock(gPMHaltLock);
10570 			for (unsigned int i = 0; i < numWorkers; i++) {
10571 				if (workers[i]) {
10572 					PMHaltWorker::checkTimeout(workers[i], &now);
10573 				}
10574 			}
10575 			IOLockLock(gPMHaltLock);
10576 		}
10577 	}
10578 	IOLockUnlock(gPMHaltLock);
10579 
10580 	// Release all workers
10581 
10582 	for (unsigned int i = 0; i < numWorkers; i++) {
10583 		if (workers[i]) {
10584 			workers[i]->release();
10585 		}
10586 		// worker also retained by it's own thread
10587 	}
10588 
10589 done:
10590 	DLOG("%s done\n", __FUNCTION__);
10591 	return;
10592 }
10593 
10594 // MARK: -
10595 // MARK: Kernel Assertion
10596 
10597 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10598 
10599 IOPMDriverAssertionID
10600 IOPMrootDomain::createPMAssertion(
10601 	IOPMDriverAssertionType whichAssertionBits,
10602 	IOPMDriverAssertionLevel assertionLevel,
10603 	IOService *ownerService,
10604 	const char *ownerDescription)
10605 {
10606 	IOReturn            ret;
10607 	IOPMDriverAssertionID     newAssertion;
10608 
10609 	if (!pmAssertions) {
10610 		return 0;
10611 	}
10612 
10613 	ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10614 
10615 	if (kIOReturnSuccess == ret) {
10616 #if (DEVELOPMENT || DEBUG)
10617 		if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10618 			const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10619 			OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10620 			    serviceName, ownerDescription);
10621 		}
10622 #endif /* (DEVELOPMENT || DEBUG) */
10623 		return newAssertion;
10624 	} else {
10625 		return 0;
10626 	}
10627 }
10628 
10629 IOReturn
10630 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10631 {
10632 #if (DEVELOPMENT || DEBUG)
10633 	if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10634 		PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10635 		if (details) {
10636 			const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10637 			    details->ownerService->getName() : NULL;
10638 			const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10639 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10640 		} else {
10641 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10642 		}
10643 	}
10644 #endif /* (DEVELOPMENT || DEBUG) */
10645 	if (!pmAssertions) {
10646 		return kIOReturnInternalError;
10647 	}
10648 	return pmAssertions->releaseAssertion(releaseAssertion);
10649 }
10650 
10651 
10652 IOReturn
10653 IOPMrootDomain::setPMAssertionLevel(
10654 	IOPMDriverAssertionID assertionID,
10655 	IOPMDriverAssertionLevel assertionLevel)
10656 {
10657 	return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10658 }
10659 
10660 IOPMDriverAssertionLevel
10661 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10662 {
10663 	IOPMDriverAssertionType       sysLevels;
10664 
10665 	if (!pmAssertions || whichAssertion == 0) {
10666 		return kIOPMDriverAssertionLevelOff;
10667 	}
10668 
10669 	sysLevels = pmAssertions->getActivatedAssertions();
10670 
10671 	// Check that every bit set in argument 'whichAssertion' is asserted
10672 	// in the aggregate bits.
10673 	if ((sysLevels & whichAssertion) == whichAssertion) {
10674 		return kIOPMDriverAssertionLevelOn;
10675 	} else {
10676 		return kIOPMDriverAssertionLevelOff;
10677 	}
10678 }
10679 
10680 IOReturn
10681 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10682 {
10683 	if (!pmAssertions) {
10684 		return kIOReturnNotFound;
10685 	}
10686 
10687 	return pmAssertions->setUserAssertionLevels(inLevels);
10688 }
10689 
10690 IOReturn
10691 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10692 {
10693 	return gIOPMWorkLoop->runActionBlock(^{
10694 		if (_driverKitMatchingAssertionCount != 0) {
10695 		        _driverKitMatchingAssertionCount++;
10696 		        return kIOReturnSuccess;
10697 		} else {
10698 		        if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10699 		                // system going to sleep
10700 		                return kIOReturnBusy;
10701 			} else {
10702 		                // createPMAssertion is asynchronous.
10703 		                // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10704 		                // The assertion is used so that on release, we reevaluate all assertions
10705 		                _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10706 		                if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10707 		                        _driverKitMatchingAssertionCount = 1;
10708 		                        return kIOReturnSuccess;
10709 				} else {
10710 		                        return kIOReturnBusy;
10711 				}
10712 			}
10713 		}
10714 	});
10715 }
10716 
10717 void
10718 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10719 {
10720 	gIOPMWorkLoop->runActionBlock(^{
10721 		if (_driverKitMatchingAssertionCount != 0) {
10722 		        _driverKitMatchingAssertionCount--;
10723 		        if (_driverKitMatchingAssertionCount == 0) {
10724 		                releasePMAssertion(_driverKitMatchingAssertion);
10725 		                _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10726 			}
10727 		} else {
10728 		        panic("Over-release of driverkit matching assertion");
10729 		}
10730 		return kIOReturnSuccess;
10731 	});
10732 }
10733 
10734 bool
10735 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10736 {
10737 	if (pmAssertions) {
10738 		pmAssertions->publishProperties();
10739 	}
10740 	return IOService::serializeProperties(s);
10741 }
10742 
10743 OSSharedPtr<OSObject>
10744 IOPMrootDomain::copyProperty( const char * aKey) const
10745 {
10746 	OSSharedPtr<OSObject> obj;
10747 	obj = IOService::copyProperty(aKey);
10748 
10749 	if (obj) {
10750 		return obj;
10751 	}
10752 
10753 	if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10754 	    sizeof(kIOPMSleepWakeWdogRebootKey))) {
10755 		if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10756 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10757 		} else {
10758 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10759 		}
10760 	}
10761 
10762 	if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10763 	    sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10764 		if (swd_flags & SWD_VALID_LOGS) {
10765 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10766 		} else {
10767 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10768 		}
10769 	}
10770 
10771 	/*
10772 	 * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey'
10773 	 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10774 	 * issued by DisplayWrangler on darkwake.
10775 	 */
10776 	if (!strcmp(aKey, "DesktopMode")) {
10777 		if (desktopMode) {
10778 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10779 		} else {
10780 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10781 		}
10782 	}
10783 	if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10784 		if (displayIdleForDemandSleep) {
10785 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10786 		} else {
10787 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10788 		}
10789 	}
10790 
10791 	if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10792 		OSSharedPtr<OSArray> array;
10793 		WAKEEVENT_LOCK();
10794 		if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10795 			OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10796 			if (collection) {
10797 				array = OSDynamicPtrCast<OSArray>(collection);
10798 			}
10799 		}
10800 		WAKEEVENT_UNLOCK();
10801 		return os::move(array);
10802 	}
10803 
10804 	if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10805 		OSSharedPtr<OSArray> array;
10806 		IOLockLock(pmStatsLock);
10807 		if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10808 			OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10809 			if (collection) {
10810 				array = OSDynamicPtrCast<OSArray>(collection);
10811 			}
10812 		}
10813 		IOLockUnlock(pmStatsLock);
10814 		return os::move(array);
10815 	}
10816 
10817 	if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10818 		OSArray *idleSleepList = NULL;
10819 		gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10820 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10821 	}
10822 
10823 	if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10824 		OSArray *systemSleepList = NULL;
10825 		gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10826 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10827 	}
10828 
10829 	if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10830 		OSArray *idleSleepList = NULL;
10831 		gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10832 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10833 	}
10834 
10835 	if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10836 		OSArray *systemSleepList = NULL;
10837 		gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10838 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10839 	}
10840 	return NULL;
10841 }
10842 
10843 // MARK: -
10844 // MARK: Wake Event Reporting
10845 
10846 void
10847 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10848 {
10849 	WAKEEVENT_LOCK();
10850 	strlcpy(outBuf, gWakeReasonString, bufSize);
10851 	WAKEEVENT_UNLOCK();
10852 }
10853 
10854 void
10855 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10856 {
10857 	WAKEEVENT_LOCK();
10858 	strlcpy(outBuf, gShutdownReasonString, bufSize);
10859 	WAKEEVENT_UNLOCK();
10860 }
10861 
10862 //******************************************************************************
10863 // acceptSystemWakeEvents
10864 //
10865 // Private control for the acceptance of driver wake event claims.
10866 //******************************************************************************
10867 
10868 void
10869 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10870 {
10871 	bool logWakeReason = false;
10872 
10873 	WAKEEVENT_LOCK();
10874 	switch (control) {
10875 	case kAcceptSystemWakeEvents_Enable:
10876 		assert(_acceptSystemWakeEvents == false);
10877 		if (!_systemWakeEventsArray) {
10878 			_systemWakeEventsArray = OSArray::withCapacity(4);
10879 		}
10880 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10881 		if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10882 			gWakeReasonString[0] = '\0';
10883 			if (_systemWakeEventsArray) {
10884 				_systemWakeEventsArray->flushCollection();
10885 			}
10886 		}
10887 
10888 		// Remove stale WakeType property before system sleep
10889 		removeProperty(kIOPMRootDomainWakeTypeKey);
10890 		removeProperty(kIOPMRootDomainWakeReasonKey);
10891 		break;
10892 
10893 	case kAcceptSystemWakeEvents_Disable:
10894 		_acceptSystemWakeEvents = false;
10895 #if defined(XNU_TARGET_OS_OSX)
10896 		logWakeReason = (gWakeReasonString[0] != '\0');
10897 #else /* !defined(XNU_TARGET_OS_OSX) */
10898 		logWakeReason = gWakeReasonSysctlRegistered;
10899 #if DEVELOPMENT
10900 		static int panic_allowed = -1;
10901 
10902 		if ((panic_allowed == -1) &&
10903 		    (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10904 			panic_allowed = 0;
10905 		}
10906 
10907 		if (panic_allowed) {
10908 			size_t i = 0;
10909 			// Panic if wake reason is null or empty
10910 			for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10911 				if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10912 					break;
10913 				}
10914 			}
10915 			if (i >= strlen(gWakeReasonString)) {
10916 				panic("Wake reason is empty");
10917 			}
10918 		}
10919 #endif /* DEVELOPMENT */
10920 #endif /* !defined(XNU_TARGET_OS_OSX) */
10921 
10922 		// publish kIOPMRootDomainWakeReasonKey if not already set
10923 		if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10924 			setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10925 		}
10926 		break;
10927 
10928 	case kAcceptSystemWakeEvents_Reenable:
10929 		assert(_acceptSystemWakeEvents == false);
10930 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10931 		removeProperty(kIOPMRootDomainWakeReasonKey);
10932 		break;
10933 	}
10934 	WAKEEVENT_UNLOCK();
10935 
10936 	if (logWakeReason) {
10937 		MSG("system wake events: %s\n", gWakeReasonString);
10938 	}
10939 }
10940 
10941 //******************************************************************************
10942 // claimSystemWakeEvent
10943 //
10944 // For a driver to claim a device is the source/conduit of a system wake event.
10945 //******************************************************************************
10946 
10947 void
10948 IOPMrootDomain::claimSystemWakeEvent(
10949 	IOService *     device,
10950 	IOOptionBits    flags,
10951 	const char *    reason,
10952 	OSObject *      details )
10953 {
10954 	OSSharedPtr<const OSSymbol>     deviceName;
10955 	OSSharedPtr<OSNumber>           deviceRegId;
10956 	OSSharedPtr<OSNumber>           claimTime;
10957 	OSSharedPtr<OSData>             flagsData;
10958 	OSSharedPtr<OSString>           reasonString;
10959 	OSSharedPtr<OSDictionary>       dict;
10960 	uint64_t                        timestamp;
10961 	bool                            addWakeReason;
10962 
10963 	if (!device || !reason) {
10964 		return;
10965 	}
10966 
10967 	pmEventTimeStamp(&timestamp);
10968 
10969 	uint64_t args[3] = {};
10970 	strlcpy((char *)args, reason, sizeof(args));
10971 	kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
10972 
10973 	IOOptionBits        aotFlags = 0;
10974 	bool                needAOTEvaluate = FALSE;
10975 
10976 	if (kIOPMAOTModeAddEventFlags & _aotMode) {
10977 		// Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
10978 		if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
10979 			flags |= kIOPMWakeEventAOTExit;
10980 		}
10981 	}
10982 
10983 #if DEVELOPMENT || DEBUG
10984 	if (_aotLingerTime && !strcmp("rtc", reason)) {
10985 		flags |= kIOPMWakeEventAOTPossibleExit;
10986 	}
10987 #endif /* DEVELOPMENT || DEBUG */
10988 
10989 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10990 	// Publishing the WakeType is serialized by the PM work loop
10991 	if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10992 		pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10993 		    (void *) _nextScheduledAlarmType.get());
10994 	}
10995 
10996 	// Workaround for the missing wake HID event
10997 	if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10998 		if (!strcmp("trackpadkeyboard", reason)) {
10999 			pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11000 			    (void *) gIOPMWakeTypeUserKey.get());
11001 		}
11002 	}
11003 #endif
11004 
11005 	deviceName   = device->copyName(gIOServicePlane);
11006 	deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11007 	claimTime    = OSNumber::withNumber(timestamp, 64);
11008 	flagsData    = OSData::withValue(flags);
11009 	reasonString = OSString::withCString(reason);
11010 	dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11011 	if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11012 		goto done;
11013 	}
11014 
11015 	dict->setObject(gIONameKey, deviceName.get());
11016 	dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11017 	dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11018 	dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11019 	dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11020 	if (details) {
11021 		dict->setObject(kIOPMWakeEventDetailsKey, details);
11022 	}
11023 
11024 	WAKEEVENT_LOCK();
11025 	addWakeReason = _acceptSystemWakeEvents;
11026 	if (_aotMode) {
11027 		IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11028 	}
11029 	aotFlags        = (kIOPMWakeEventAOTFlags & flags);
11030 	aotFlags        = (aotFlags & ~_aotPendingFlags);
11031 	needAOTEvaluate = false;
11032 	if (_aotNow && aotFlags) {
11033 		if (kIOPMWakeEventAOTPossibleExit & flags) {
11034 			_aotMetrics->possibleCount++;
11035 		}
11036 		if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11037 			_aotMetrics->confirmedPossibleCount++;
11038 		}
11039 		if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11040 			_aotMetrics->rejectedPossibleCount++;
11041 		}
11042 		if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11043 			_aotMetrics->expiredPossibleCount++;
11044 		}
11045 
11046 		_aotPendingFlags |= aotFlags;
11047 		addWakeReason     = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11048 		needAOTEvaluate   = _aotReadyToFullWake;
11049 	}
11050 	DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11051 	    reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11052 	    _aotNow, pmTracer->getTracePhase(), addWakeReason);
11053 
11054 #if DEVELOPMENT || DEBUG
11055 	if (addWakeReason) {
11056 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
11057 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11058 		    "Report System Wake Event",
11059 		    "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11060 		    reason,
11061 		    (int)flags,
11062 		    deviceName->getCStringNoCopy(),
11063 		    device->getRegistryEntryID()
11064 		    );
11065 	}
11066 #endif /* DEVELOPMENT || DEBUG */
11067 
11068 	if (!gWakeReasonSysctlRegistered) {
11069 		// Lazy registration until the platform driver stops registering
11070 		// the same name.
11071 		gWakeReasonSysctlRegistered = true;
11072 	}
11073 	if (addWakeReason) {
11074 		_systemWakeEventsArray->setObject(dict.get());
11075 		if (gWakeReasonString[0] != '\0') {
11076 			strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11077 		}
11078 		strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11079 	}
11080 
11081 	WAKEEVENT_UNLOCK();
11082 	if (needAOTEvaluate) {
11083 		// Call aotEvaluate() on PM work loop since it may call
11084 		// aotExit() which accesses PM state.
11085 		pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11086 	}
11087 
11088 done:
11089 	return;
11090 }
11091 
11092 //******************************************************************************
11093 // claimSystemBootEvent
11094 //
11095 // For a driver to claim a device is the source/conduit of a system boot event.
11096 //******************************************************************************
11097 
11098 void
11099 IOPMrootDomain::claimSystemBootEvent(
11100 	IOService *              device,
11101 	IOOptionBits             flags,
11102 	const char *             reason,
11103 	__unused OSObject *      details )
11104 {
11105 	if (!device || !reason) {
11106 		return;
11107 	}
11108 
11109 	DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11110 #if DEVELOPMENT || DEBUG
11111 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11112 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11113 	    "Report System Boot Device",
11114 	    "Reason: %s Flags: 0x%x Device: %s",
11115 	    reason,
11116 	    (int)flags,
11117 	    device->getName()
11118 	    );
11119 #endif /* DEVELOPMENT || DEBUG */
11120 	WAKEEVENT_LOCK();
11121 	if (!gBootReasonSysctlRegistered) {
11122 		// Lazy sysctl registration after setting gBootReasonString
11123 		strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11124 		os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11125 	}
11126 	WAKEEVENT_UNLOCK();
11127 }
11128 
11129 //******************************************************************************
11130 // claimSystemShutdownEvent
11131 //
11132 // For drivers to claim a system shutdown event on the ensuing boot.
11133 //******************************************************************************
11134 
11135 void
11136 IOPMrootDomain::claimSystemShutdownEvent(
11137 	IOService *              device,
11138 	IOOptionBits             flags,
11139 	const char *             reason,
11140 	__unused OSObject *      details )
11141 {
11142 	if (!device || !reason) {
11143 		return;
11144 	}
11145 
11146 	DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11147 #if DEVELOPMENT || DEBUG
11148 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11149 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11150 	    "Report System Shutdown Cause From Previous Boot",
11151 	    "Reason: %s Flags: 0x%x Device: %s",
11152 	    reason,
11153 	    (int)flags,
11154 	    device->getName()
11155 	    );
11156 #endif /* DEVELOPMENT || DEBUG */
11157 	WAKEEVENT_LOCK();
11158 	if (gShutdownReasonString[0] != '\0') {
11159 		strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11160 	}
11161 	strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11162 
11163 	gShutdownReasonSysctlRegistered = true;
11164 	WAKEEVENT_UNLOCK();
11165 }
11166 
11167 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11168 
11169 // MARK: -
11170 // MARK: PMSettingHandle
11171 
11172 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11173 
11174 void
11175 PMSettingHandle::free( void )
11176 {
11177 	if (pmso) {
11178 		pmso->clientHandleFreed();
11179 		pmso->release();
11180 		pmso = NULL;
11181 	}
11182 
11183 	OSObject::free();
11184 }
11185 
11186 // MARK: -
11187 // MARK: PMSettingObject
11188 
11189 #undef super
11190 #define super OSObject
11191 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11192 
11193 /*
11194  * Static constructor/initializer for PMSettingObject
11195  */
11196 PMSettingObject *PMSettingObject::pmSettingObject(
11197 	IOPMrootDomain                      * parent_arg,
11198 	IOPMSettingControllerCallback       handler_arg,
11199 	OSObject                            * target_arg,
11200 	uintptr_t                           refcon_arg,
11201 	uint32_t                            supportedPowerSources,
11202 	const OSSymbol *                    settings[],
11203 	OSObject                            * *handle_obj)
11204 {
11205 	uint32_t                            settingCount = 0;
11206 	PMSettingObject                     *pmso = NULL;
11207 	PMSettingHandle                     *pmsh = NULL;
11208 
11209 	if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11210 		return NULL;
11211 	}
11212 
11213 	// count OSSymbol entries in NULL terminated settings array
11214 	while (settings[settingCount]) {
11215 		settingCount++;
11216 	}
11217 	if (0 == settingCount) {
11218 		return NULL;
11219 	}
11220 
11221 	pmso = new PMSettingObject;
11222 	if (!pmso || !pmso->init()) {
11223 		goto fail;
11224 	}
11225 
11226 	pmsh = new PMSettingHandle;
11227 	if (!pmsh || !pmsh->init()) {
11228 		goto fail;
11229 	}
11230 
11231 	queue_init(&pmso->calloutQueue);
11232 	pmso->parent       = parent_arg;
11233 	pmso->func         = handler_arg;
11234 	pmso->target       = target_arg;
11235 	pmso->refcon       = refcon_arg;
11236 	pmso->settingCount = settingCount;
11237 
11238 	pmso->retain(); // handle holds a retain on pmso
11239 	pmsh->pmso = pmso;
11240 	pmso->pmsh = pmsh;
11241 
11242 	pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11243 	if (pmso->publishedFeatureID) {
11244 		for (unsigned int i = 0; i < settingCount; i++) {
11245 			// Since there is now at least one listener to this setting, publish
11246 			// PM root domain support for it.
11247 			parent_arg->publishPMSetting( settings[i],
11248 			    supportedPowerSources, &pmso->publishedFeatureID[i] );
11249 		}
11250 	}
11251 
11252 	*handle_obj = pmsh;
11253 	return pmso;
11254 
11255 fail:
11256 	if (pmso) {
11257 		pmso->release();
11258 	}
11259 	if (pmsh) {
11260 		pmsh->release();
11261 	}
11262 	return NULL;
11263 }
11264 
11265 void
11266 PMSettingObject::free( void )
11267 {
11268 	if (publishedFeatureID) {
11269 		for (const auto& featureID : publishedFeatureID) {
11270 			if (featureID) {
11271 				parent->removePublishedFeature( featureID );
11272 			}
11273 		}
11274 
11275 		publishedFeatureID = {};
11276 	}
11277 
11278 	super::free();
11279 }
11280 
11281 IOReturn
11282 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11283 {
11284 	return (*func)(target, type, object, refcon);
11285 }
11286 
11287 void
11288 PMSettingObject::clientHandleFreed( void )
11289 {
11290 	parent->deregisterPMSettingObject(this);
11291 }
11292 
11293 // MARK: -
11294 // MARK: PMAssertionsTracker
11295 
11296 //*********************************************************************************
11297 //*********************************************************************************
11298 //*********************************************************************************
11299 // class PMAssertionsTracker Implementation
11300 
11301 #define kAssertUniqueIDStart    500
11302 
11303 PMAssertionsTracker *
11304 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11305 {
11306 	PMAssertionsTracker    *me;
11307 
11308 	me = new PMAssertionsTracker;
11309 	if (!me || !me->init()) {
11310 		if (me) {
11311 			me->release();
11312 		}
11313 		return NULL;
11314 	}
11315 
11316 	me->owner = rootDomain;
11317 	me->issuingUniqueID = kAssertUniqueIDStart;
11318 	me->assertionsArray = OSArray::withCapacity(5);
11319 	me->assertionsKernel = 0;
11320 	me->assertionsUser = 0;
11321 	me->assertionsCombined = 0;
11322 	me->assertionsArrayLock = IOLockAlloc();
11323 	me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11324 
11325 	assert(me->assertionsArray);
11326 	assert(me->assertionsArrayLock);
11327 
11328 	return me;
11329 }
11330 
11331 /* tabulate
11332  * - Update assertionsKernel to reflect the state of all
11333  * assertions in the kernel.
11334  * - Update assertionsCombined to reflect both kernel & user space.
11335  */
11336 void
11337 PMAssertionsTracker::tabulate(void)
11338 {
11339 	int i;
11340 	int count;
11341 	const PMAssertStruct *_a = nullptr;
11342 	OSValueObject<PMAssertStruct> *_d = nullptr;
11343 
11344 	IOPMDriverAssertionType oldKernel = assertionsKernel;
11345 	IOPMDriverAssertionType oldCombined = assertionsCombined;
11346 
11347 	ASSERT_GATED();
11348 
11349 	assertionsKernel = 0;
11350 	assertionsCombined = 0;
11351 
11352 	if (!assertionsArray) {
11353 		return;
11354 	}
11355 
11356 	if ((count = assertionsArray->getCount())) {
11357 		for (i = 0; i < count; i++) {
11358 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11359 			if (_d) {
11360 				_a = _d->getBytesNoCopy();
11361 				if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11362 					assertionsKernel |= _a->assertionBits;
11363 				}
11364 			}
11365 		}
11366 	}
11367 
11368 	tabulateProducerCount++;
11369 	assertionsCombined = assertionsKernel | assertionsUser;
11370 
11371 	if ((assertionsKernel != oldKernel) ||
11372 	    (assertionsCombined != oldCombined)) {
11373 		owner->evaluateAssertions(assertionsCombined, oldCombined);
11374 	}
11375 }
11376 
11377 void
11378 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11379 {
11380 	AbsoluteTime now;
11381 	uint64_t     nsec;
11382 
11383 	if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11384 	    (assertStruct->assertCPUStartTime == 0)) {
11385 		return;
11386 	}
11387 
11388 	now = mach_absolute_time();
11389 	SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11390 	absolutetime_to_nanoseconds(now, &nsec);
11391 	assertStruct->assertCPUDuration += nsec;
11392 	assertStruct->assertCPUStartTime = 0;
11393 
11394 	if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11395 		maxAssertCPUDuration = assertStruct->assertCPUDuration;
11396 		maxAssertCPUEntryId = assertStruct->registryEntryID;
11397 	}
11398 }
11399 
11400 void
11401 PMAssertionsTracker::reportCPUBitAccounting( void )
11402 {
11403 	const PMAssertStruct *_a = nullptr;
11404 	OSValueObject<PMAssertStruct> *_d = nullptr;
11405 	int            i, count;
11406 	AbsoluteTime   now;
11407 	uint64_t       nsec;
11408 
11409 	ASSERT_GATED();
11410 
11411 	// Account for drivers that are still holding the CPU assertion
11412 	if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11413 		now = mach_absolute_time();
11414 		if ((count = assertionsArray->getCount())) {
11415 			for (i = 0; i < count; i++) {
11416 				_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11417 				if (_d) {
11418 					_a = _d->getBytesNoCopy();
11419 					if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11420 					    (_a->level == kIOPMDriverAssertionLevelOn) &&
11421 					    (_a->assertCPUStartTime != 0)) {
11422 						// Don't modify PMAssertStruct, leave that
11423 						// for updateCPUBitAccounting()
11424 						SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11425 						absolutetime_to_nanoseconds(now, &nsec);
11426 						nsec += _a->assertCPUDuration;
11427 						if (nsec > maxAssertCPUDuration) {
11428 							maxAssertCPUDuration = nsec;
11429 							maxAssertCPUEntryId = _a->registryEntryID;
11430 						}
11431 					}
11432 				}
11433 			}
11434 		}
11435 	}
11436 
11437 	if (maxAssertCPUDuration) {
11438 		DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11439 		    (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11440 	}
11441 
11442 	maxAssertCPUDuration = 0;
11443 	maxAssertCPUEntryId = 0;
11444 }
11445 
11446 void
11447 PMAssertionsTracker::publishProperties( void )
11448 {
11449 	OSSharedPtr<OSArray>             assertionsSummary;
11450 
11451 	if (tabulateConsumerCount != tabulateProducerCount) {
11452 		IOLockLock(assertionsArrayLock);
11453 
11454 		tabulateConsumerCount = tabulateProducerCount;
11455 
11456 		/* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11457 		 */
11458 		assertionsSummary = copyAssertionsArray();
11459 		if (assertionsSummary) {
11460 			owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11461 		} else {
11462 			owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11463 		}
11464 
11465 		/* Publish the IOPMrootDomain property "DriverPMAssertions"
11466 		 */
11467 		owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11468 
11469 		IOLockUnlock(assertionsArrayLock);
11470 	}
11471 }
11472 
11473 PMAssertStruct *
11474 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11475 {
11476 	PMAssertStruct      *_a = NULL;
11477 	OSValueObject<PMAssertStruct> *_d = nullptr;
11478 	int                 found = -1;
11479 	int                 count = 0;
11480 	int                 i = 0;
11481 
11482 	if (assertionsArray
11483 	    && (count = assertionsArray->getCount())) {
11484 		for (i = 0; i < count; i++) {
11485 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11486 			if (_d) {
11487 				_a = _d->getMutableBytesNoCopy();
11488 				if (_a && (_id == _a->id)) {
11489 					found = i;
11490 					break;
11491 				}
11492 			}
11493 		}
11494 	}
11495 
11496 	if (-1 == found) {
11497 		return NULL;
11498 	} else {
11499 		if (index) {
11500 			*index = found;
11501 		}
11502 		return _a;
11503 	}
11504 }
11505 
11506 /* PMAssertionsTracker::handleCreateAssertion
11507  * Perform assertion work on the PM workloop. Do not call directly.
11508  */
11509 IOReturn
11510 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11511 {
11512 	PMAssertStruct *assertStruct = nullptr;
11513 
11514 	ASSERT_GATED();
11515 
11516 	if (newAssertion) {
11517 		IOLockLock(assertionsArrayLock);
11518 		assertStruct = newAssertion->getMutableBytesNoCopy();
11519 		if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11520 		    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11521 			assertStruct->assertCPUStartTime = mach_absolute_time();
11522 		}
11523 		assertionsArray->setObject(newAssertion);
11524 		IOLockUnlock(assertionsArrayLock);
11525 		newAssertion->release();
11526 
11527 		tabulate();
11528 	}
11529 	return kIOReturnSuccess;
11530 }
11531 
11532 /* PMAssertionsTracker::createAssertion
11533  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11534  * appropiate.
11535  */
11536 IOReturn
11537 PMAssertionsTracker::createAssertion(
11538 	IOPMDriverAssertionType which,
11539 	IOPMDriverAssertionLevel level,
11540 	IOService *serviceID,
11541 	const char *whoItIs,
11542 	IOPMDriverAssertionID *outID)
11543 {
11544 	OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11545 	PMAssertStruct  track;
11546 
11547 	// Warning: trillions and trillions of created assertions may overflow the unique ID.
11548 	track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11549 	track.level = level;
11550 	track.assertionBits = which;
11551 
11552 	// NB: ownerString is explicitly managed by PMAssertStruct
11553 	// it will be released in `handleReleaseAssertion' below
11554 	track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11555 	track.ownerService = serviceID;
11556 	track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11557 	track.modifiedTime = 0;
11558 	pmEventTimeStamp(&track.createdTime);
11559 	track.assertCPUStartTime = 0;
11560 	track.assertCPUDuration = 0;
11561 
11562 	dataStore = OSValueObjectWithValue(track);
11563 	if (!dataStore) {
11564 		if (track.ownerString) {
11565 			track.ownerString->release();
11566 			track.ownerString = NULL;
11567 		}
11568 		return kIOReturnNoMemory;
11569 	}
11570 
11571 	*outID = track.id;
11572 
11573 	if (owner && owner->pmPowerStateQueue) {
11574 		// queue action is responsible for releasing dataStore
11575 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11576 	}
11577 
11578 	return kIOReturnSuccess;
11579 }
11580 
11581 /* PMAssertionsTracker::handleReleaseAssertion
11582  * Runs in PM workloop. Do not call directly.
11583  */
11584 IOReturn
11585 PMAssertionsTracker::handleReleaseAssertion(
11586 	IOPMDriverAssertionID _id)
11587 {
11588 	ASSERT_GATED();
11589 
11590 	int             index;
11591 	PMAssertStruct  *assertStruct = detailsForID(_id, &index);
11592 
11593 	if (!assertStruct) {
11594 		return kIOReturnNotFound;
11595 	}
11596 
11597 	IOLockLock(assertionsArrayLock);
11598 
11599 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11600 	    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11601 		updateCPUBitAccounting(assertStruct);
11602 	}
11603 
11604 	if (assertStruct->ownerString) {
11605 		assertStruct->ownerString->release();
11606 		assertStruct->ownerString = NULL;
11607 	}
11608 
11609 	assertionsArray->removeObject(index);
11610 	IOLockUnlock(assertionsArrayLock);
11611 
11612 	tabulate();
11613 	return kIOReturnSuccess;
11614 }
11615 
11616 /* PMAssertionsTracker::releaseAssertion
11617  * Releases an assertion and affects system behavior if appropiate.
11618  * Actual work happens on PM workloop.
11619  */
11620 IOReturn
11621 PMAssertionsTracker::releaseAssertion(
11622 	IOPMDriverAssertionID _id)
11623 {
11624 	if (owner && owner->pmPowerStateQueue) {
11625 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11626 	}
11627 	return kIOReturnSuccess;
11628 }
11629 
11630 /* PMAssertionsTracker::handleSetAssertionLevel
11631  * Runs in PM workloop. Do not call directly.
11632  */
11633 IOReturn
11634 PMAssertionsTracker::handleSetAssertionLevel(
11635 	IOPMDriverAssertionID    _id,
11636 	IOPMDriverAssertionLevel _level)
11637 {
11638 	PMAssertStruct      *assertStruct = detailsForID(_id, NULL);
11639 
11640 	ASSERT_GATED();
11641 
11642 	if (!assertStruct) {
11643 		return kIOReturnNotFound;
11644 	}
11645 
11646 	IOLockLock(assertionsArrayLock);
11647 	pmEventTimeStamp(&assertStruct->modifiedTime);
11648 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11649 	    (assertStruct->level != _level)) {
11650 		if (_level == kIOPMDriverAssertionLevelOn) {
11651 			assertStruct->assertCPUStartTime = mach_absolute_time();
11652 		} else {
11653 			updateCPUBitAccounting(assertStruct);
11654 		}
11655 	}
11656 	assertStruct->level = _level;
11657 	IOLockUnlock(assertionsArrayLock);
11658 
11659 	tabulate();
11660 	return kIOReturnSuccess;
11661 }
11662 
11663 /* PMAssertionsTracker::setAssertionLevel
11664  */
11665 IOReturn
11666 PMAssertionsTracker::setAssertionLevel(
11667 	IOPMDriverAssertionID    _id,
11668 	IOPMDriverAssertionLevel _level)
11669 {
11670 	if (owner && owner->pmPowerStateQueue) {
11671 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11672 		    (void *)(uintptr_t)_level, _id);
11673 	}
11674 
11675 	return kIOReturnSuccess;
11676 }
11677 
11678 IOReturn
11679 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11680 {
11681 	IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11682 
11683 	ASSERT_GATED();
11684 
11685 	if (new_user_levels != assertionsUser) {
11686 		DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11687 		assertionsUser = new_user_levels;
11688 	}
11689 
11690 	tabulate();
11691 	return kIOReturnSuccess;
11692 }
11693 
11694 IOReturn
11695 PMAssertionsTracker::setUserAssertionLevels(
11696 	IOPMDriverAssertionType new_user_levels)
11697 {
11698 	if (gIOPMWorkLoop) {
11699 		gIOPMWorkLoop->runAction(
11700 			OSMemberFunctionCast(
11701 				IOWorkLoop::Action,
11702 				this,
11703 				&PMAssertionsTracker::handleSetUserAssertionLevels),
11704 			this,
11705 			(void *) &new_user_levels, NULL, NULL, NULL);
11706 	}
11707 
11708 	return kIOReturnSuccess;
11709 }
11710 
11711 
11712 OSSharedPtr<OSArray>
11713 PMAssertionsTracker::copyAssertionsArray(void)
11714 {
11715 	int count;
11716 	int i;
11717 	OSSharedPtr<OSArray>     outArray = NULL;
11718 
11719 	if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11720 		goto exit;
11721 	}
11722 	outArray = OSArray::withCapacity(count);
11723 	if (!outArray) {
11724 		goto exit;
11725 	}
11726 
11727 	for (i = 0; i < count; i++) {
11728 		const PMAssertStruct *_a = nullptr;
11729 		OSValueObject<PMAssertStruct> *_d = nullptr;
11730 		OSSharedPtr<OSDictionary>    details;
11731 
11732 		_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11733 		if (_d && (_a = _d->getBytesNoCopy())) {
11734 			OSSharedPtr<OSNumber>        _n;
11735 
11736 			details = OSDictionary::withCapacity(7);
11737 			if (!details) {
11738 				continue;
11739 			}
11740 
11741 			outArray->setObject(details.get());
11742 
11743 			_n = OSNumber::withNumber(_a->id, 64);
11744 			if (_n) {
11745 				details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11746 			}
11747 			_n = OSNumber::withNumber(_a->createdTime, 64);
11748 			if (_n) {
11749 				details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11750 			}
11751 			_n = OSNumber::withNumber(_a->modifiedTime, 64);
11752 			if (_n) {
11753 				details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11754 			}
11755 			_n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11756 			if (_n) {
11757 				details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11758 			}
11759 			_n = OSNumber::withNumber(_a->level, 64);
11760 			if (_n) {
11761 				details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11762 			}
11763 			_n = OSNumber::withNumber(_a->assertionBits, 64);
11764 			if (_n) {
11765 				details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11766 			}
11767 
11768 			if (_a->ownerString) {
11769 				details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11770 			}
11771 		}
11772 	}
11773 
11774 exit:
11775 	return os::move(outArray);
11776 }
11777 
11778 IOPMDriverAssertionType
11779 PMAssertionsTracker::getActivatedAssertions(void)
11780 {
11781 	return assertionsCombined;
11782 }
11783 
11784 IOPMDriverAssertionLevel
11785 PMAssertionsTracker::getAssertionLevel(
11786 	IOPMDriverAssertionType type)
11787 {
11788 	// FIXME: unused and also wrong
11789 	if (type && ((type & assertionsKernel) == assertionsKernel)) {
11790 		return kIOPMDriverAssertionLevelOn;
11791 	} else {
11792 		return kIOPMDriverAssertionLevelOff;
11793 	}
11794 }
11795 
11796 //*********************************************************************************
11797 //*********************************************************************************
11798 //*********************************************************************************
11799 
11800 
11801 static void
11802 pmEventTimeStamp(uint64_t *recordTS)
11803 {
11804 	clock_sec_t     tsec;
11805 	clock_usec_t    tusec;
11806 
11807 	if (!recordTS) {
11808 		return;
11809 	}
11810 
11811 	// We assume tsec fits into 32 bits; 32 bits holds enough
11812 	// seconds for 136 years since the epoch in 1970.
11813 	clock_get_calendar_microtime(&tsec, &tusec);
11814 
11815 
11816 	// Pack the sec & microsec calendar time into a uint64_t, for fun.
11817 	*recordTS = 0;
11818 	*recordTS |= (uint32_t)tusec;
11819 	*recordTS |= ((uint64_t)tsec << 32);
11820 
11821 	return;
11822 }
11823 
11824 // MARK: -
11825 // MARK: IORootParent
11826 
11827 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11828 
11829 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11830 
11831 // The reason that root domain needs a root parent is to facilitate demand
11832 // sleep, since a power change from the root parent cannot be vetoed.
11833 //
11834 // The above statement is no longer true since root domain now performs
11835 // demand sleep using overrides. But root parent remains to avoid changing
11836 // the power tree stacking. Root parent is parked at the max power state.
11837 
11838 
11839 static IOPMPowerState patriarchPowerStates[2] =
11840 {
11841 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11842 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11843 };
11844 
11845 void
11846 IORootParent::initialize( void )
11847 {
11848 
11849 	gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11850 	gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11851 	gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11852 	gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11853 	gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11854 	gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11855 	gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11856 	gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11857 	gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11858 	gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11859 	gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11860 	gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11861 	gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11862 	gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11863 	gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11864 	gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11865 	gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11866 	gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11867 	gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11868 	gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11869 	gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11870 	gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11871 	gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11872 	gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11873 	gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11874 	gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11875 	gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11876 	gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11877 	gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11878 	gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11879 	gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11880 	gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11881 	gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11882 	gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11883 	gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11884 	gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11885 	gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11886 	gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11887 	gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11888 	gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11889 	gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11890 	gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11891 	gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11892 	gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11893 }
11894 
11895 bool
11896 IORootParent::start( IOService * nub )
11897 {
11898 	IOService::start(nub);
11899 	attachToParent( getRegistryRoot(), gIOPowerPlane );
11900 	PMinit();
11901 	registerPowerDriver(this, patriarchPowerStates, 2);
11902 	makeUsable();
11903 	return true;
11904 }
11905 
11906 void
11907 IORootParent::shutDownSystem( void )
11908 {
11909 }
11910 
11911 void
11912 IORootParent::restartSystem( void )
11913 {
11914 }
11915 
11916 void
11917 IORootParent::sleepSystem( void )
11918 {
11919 }
11920 
11921 void
11922 IORootParent::dozeSystem( void )
11923 {
11924 }
11925 
11926 void
11927 IORootParent::sleepToDoze( void )
11928 {
11929 }
11930 
11931 void
11932 IORootParent::wakeSystem( void )
11933 {
11934 }
11935 
11936 OSSharedPtr<OSObject>
11937 IORootParent::copyProperty( const char * aKey) const
11938 {
11939 	return IOService::copyProperty(aKey);
11940 }
11941 
11942 uint32_t
11943 IOPMrootDomain::getWatchdogTimeout()
11944 {
11945 	if (gSwdSleepWakeTimeout) {
11946 		gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11947 	}
11948 	if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11949 	    (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11950 		return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11951 	} else {
11952 		return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11953 	}
11954 }
11955 
11956 
11957 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11958 IOReturn
11959 IOPMrootDomain::restartWithStackshot()
11960 {
11961 	takeStackshot(true);
11962 
11963 	return kIOReturnSuccess;
11964 }
11965 
11966 void
11967 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11968 {
11969 	takeStackshot(wdogTrigger);
11970 }
11971 
11972 void
11973 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11974 {
11975 	switch (tracePhase) {
11976 	case kIOPMTracePointSleepStarted:
11977 		*phaseString = "kIOPMTracePointSleepStarted";
11978 		*description = "starting sleep";
11979 		break;
11980 
11981 	case kIOPMTracePointSleepApplications:
11982 		*phaseString = "kIOPMTracePointSleepApplications";
11983 		*description = "notifying applications";
11984 		break;
11985 
11986 	case kIOPMTracePointSleepPriorityClients:
11987 		*phaseString = "kIOPMTracePointSleepPriorityClients";
11988 		*description = "notifying clients about upcoming system capability changes";
11989 		break;
11990 
11991 	case kIOPMTracePointSleepWillChangeInterests:
11992 		*phaseString = "kIOPMTracePointSleepWillChangeInterests";
11993 		*description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11994 		break;
11995 
11996 	case kIOPMTracePointSleepPowerPlaneDrivers:
11997 		*phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11998 		*description = "calling power state change callbacks";
11999 		break;
12000 
12001 	case kIOPMTracePointSleepDidChangeInterests:
12002 		*phaseString = "kIOPMTracePointSleepDidChangeInterests";
12003 		*description = "calling rootDomain's clients about rootDomain's state changes";
12004 		break;
12005 
12006 	case kIOPMTracePointSleepCapabilityClients:
12007 		*phaseString = "kIOPMTracePointSleepCapabilityClients";
12008 		*description = "notifying clients about current system capabilities";
12009 		break;
12010 
12011 	case kIOPMTracePointSleepPlatformActions:
12012 		*phaseString = "kIOPMTracePointSleepPlatformActions";
12013 		*description = "calling Quiesce/Sleep action callbacks";
12014 		break;
12015 
12016 	case kIOPMTracePointSleepCPUs:
12017 	{
12018 		*phaseString = "kIOPMTracePointSleepCPUs";
12019 #if defined(__i386__) || defined(__x86_64__)
12020 		/*
12021 		 * We cannot use the getCPUNumber() method to get the cpu number, since
12022 		 * that cpu number is unrelated to the cpu number we need (we need the cpu
12023 		 * number as enumerated by the scheduler, NOT the CPU number enumerated
12024 		 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12025 		 * Instead, pass the Mach processor pointer associated with the current
12026 		 * shutdown target so its associated cpu_id can be used in
12027 		 * processor_to_datastring.
12028 		 */
12029 		if (currentShutdownTarget != NULL &&
12030 		    currentShutdownTarget->getMachProcessor() != NULL) {
12031 			const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12032 			    currentShutdownTarget->getMachProcessor());
12033 			*description = sbuf;
12034 		} else {
12035 			*description = "halting all non-boot CPUs";
12036 		}
12037 #else
12038 		*description = "halting all non-boot CPUs";
12039 #endif
12040 		break;
12041 	}
12042 	case kIOPMTracePointSleepPlatformDriver:
12043 		*phaseString = "kIOPMTracePointSleepPlatformDriver";
12044 		*description = "executing platform specific code";
12045 		break;
12046 
12047 	case kIOPMTracePointHibernate:
12048 		*phaseString = "kIOPMTracePointHibernate";
12049 		*description = "writing the hibernation image";
12050 		break;
12051 
12052 	case kIOPMTracePointSystemSleep:
12053 		*phaseString = "kIOPMTracePointSystemSleep";
12054 		*description = "in EFI/Bootrom after last point of entry to sleep";
12055 		break;
12056 
12057 	case kIOPMTracePointWakePlatformDriver:
12058 		*phaseString = "kIOPMTracePointWakePlatformDriver";
12059 		*description = "executing platform specific code";
12060 		break;
12061 
12062 
12063 	case kIOPMTracePointWakePlatformActions:
12064 		*phaseString = "kIOPMTracePointWakePlatformActions";
12065 		*description = "calling Wake action callbacks";
12066 		break;
12067 
12068 	case kIOPMTracePointWakeCPUs:
12069 		*phaseString = "kIOPMTracePointWakeCPUs";
12070 		*description = "starting non-boot CPUs";
12071 		break;
12072 
12073 	case kIOPMTracePointWakeWillPowerOnClients:
12074 		*phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12075 		*description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12076 		break;
12077 
12078 	case kIOPMTracePointWakeWillChangeInterests:
12079 		*phaseString = "kIOPMTracePointWakeWillChangeInterests";
12080 		*description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12081 		break;
12082 
12083 	case kIOPMTracePointWakeDidChangeInterests:
12084 		*phaseString = "kIOPMTracePointWakeDidChangeInterests";
12085 		*description = "calling rootDomain's clients about completed rootDomain's state changes";
12086 		break;
12087 
12088 	case kIOPMTracePointWakePowerPlaneDrivers:
12089 		*phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12090 		*description = "calling power state change callbacks";
12091 		break;
12092 
12093 	case kIOPMTracePointWakeCapabilityClients:
12094 		*phaseString = "kIOPMTracePointWakeCapabilityClients";
12095 		*description = "informing clients about current system capabilities";
12096 		break;
12097 
12098 	case kIOPMTracePointWakeApplications:
12099 		*phaseString = "kIOPMTracePointWakeApplications";
12100 		*description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12101 		break;
12102 
12103 	case kIOPMTracePointDarkWakeEntry:
12104 		*phaseString = "kIOPMTracePointDarkWakeEntry";
12105 		*description = "entering darkwake on way to sleep";
12106 		break;
12107 
12108 	case kIOPMTracePointDarkWakeExit:
12109 		*phaseString = "kIOPMTracePointDarkWakeExit";
12110 		*description = "entering fullwake from darkwake";
12111 		break;
12112 
12113 	default:
12114 		*phaseString = NULL;
12115 		*description = NULL;
12116 	}
12117 }
12118 
12119 void
12120 IOPMrootDomain::saveFailureData2File()
12121 {
12122 	unsigned int len = 0;
12123 	char  failureStr[512];
12124 	errno_t error;
12125 	char *outbuf;
12126 	OSNumber *statusCode;
12127 	uint64_t pmStatusCode = 0;
12128 	uint32_t phaseData = 0;
12129 	uint32_t phaseDetail = 0;
12130 	bool efiFailure = false;
12131 
12132 	OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12133 	statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12134 	if (statusCode) {
12135 		pmStatusCode = statusCode->unsigned64BitValue();
12136 		phaseData = pmStatusCode & 0xFFFFFFFF;
12137 		phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12138 		if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12139 			LOG("Sleep Wake failure in EFI\n");
12140 			efiFailure = true;
12141 			failureStr[0] = 0;
12142 			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);
12143 			len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12144 		}
12145 	}
12146 
12147 	if (!efiFailure) {
12148 		if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12149 			swd_flags |= SWD_BOOT_BY_SW_WDOG;
12150 			PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12151 			// dump panic will handle saving nvram data
12152 			return;
12153 		}
12154 
12155 		/* Keeping this around for capturing data during power
12156 		 * button press */
12157 
12158 		if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12159 			DLOG("No sleep wake failure string\n");
12160 			return;
12161 		}
12162 		if (len == 0) {
12163 			DLOG("Ignoring zero byte SleepWake failure string\n");
12164 			goto exit;
12165 		}
12166 
12167 		// if PMStatus code is zero, delete stackshot and return
12168 		if (statusCode) {
12169 			if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12170 				// there was no sleep wake failure
12171 				// this can happen if delete stackshot was called
12172 				// before take stackshot completed. Let us delete any
12173 				// sleep wake failure data in nvram
12174 				DLOG("Deleting stackshot on successful wake\n");
12175 				deleteStackshot();
12176 				return;
12177 			}
12178 		}
12179 
12180 		if (len > sizeof(failureStr)) {
12181 			len = sizeof(failureStr);
12182 		}
12183 		failureStr[0] = 0;
12184 		PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12185 	}
12186 	if (failureStr[0] != 0) {
12187 		error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12188 		if (error) {
12189 			DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12190 		} else {
12191 			DLOG("Saved SleepWake failure string to file.\n");
12192 		}
12193 	}
12194 
12195 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12196 		goto exit;
12197 	}
12198 
12199 	if (swd_buffer) {
12200 		unsigned int len = 0;
12201 		errno_t error;
12202 		char nvram_var_name_buffer[20];
12203 		unsigned int concat_len = 0;
12204 		swd_hdr      *hdr = NULL;
12205 
12206 
12207 		hdr = (swd_hdr *)swd_buffer;
12208 		outbuf = (char *)hdr + hdr->spindump_offset;
12209 		OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12210 
12211 		for (int i = 0; i < 8; i++) {
12212 			snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12213 			if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12214 				LOG("No SleepWake blob to read beyond chunk %d\n", i);
12215 				break;
12216 			}
12217 			if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12218 				PERemoveNVRAMProperty(nvram_var_name_buffer);
12219 				LOG("Could not read the property :-(\n");
12220 				break;
12221 			}
12222 			PERemoveNVRAMProperty(nvram_var_name_buffer);
12223 			concat_len += len;
12224 		}
12225 		LOG("Concatenated length for the SWD blob %d\n", concat_len);
12226 
12227 		if (concat_len) {
12228 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12229 			if (error) {
12230 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12231 			} else {
12232 				LOG("Saved SleepWake zipped data to file.\n");
12233 			}
12234 		} else {
12235 			// There is a sleep wake failure string but no stackshot
12236 			// Write a placeholder stacks file so that swd runs
12237 			snprintf(outbuf, 20, "%s", "No stackshot data\n");
12238 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12239 			if (error) {
12240 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12241 			} else {
12242 				LOG("Saved SleepWake zipped data to file.\n");
12243 			}
12244 		}
12245 	} else {
12246 		LOG("No buffer allocated to save failure stackshot\n");
12247 	}
12248 
12249 
12250 	gRootDomain->swd_lock = 0;
12251 exit:
12252 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12253 	return;
12254 }
12255 
12256 
12257 void
12258 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12259 {
12260 	OSSharedPtr<IORegistryIterator>    iter;
12261 	OSSharedPtr<const OSSymbol>        kextName = NULL;
12262 	IORegistryEntry *       entry;
12263 	IOService *             node;
12264 	bool                    nodeFound = false;
12265 
12266 	const void *            callMethod = NULL;
12267 	const char *            objectName = NULL;
12268 	const char *            phaseString = NULL;
12269 	const char *            phaseDescription = NULL;
12270 	uint64_t                delta;
12271 
12272 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12273 	uint32_t tracePhase = pmTracer->getTracePhase();
12274 
12275 	*thread = NULL;
12276 
12277 	delta = get_watchdog_elapsed_time();
12278 	if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12279 		snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12280 	} else {
12281 		snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12282 	}
12283 	tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12284 
12285 	if (notifierThread) {
12286 		if (notifier && (notifier->identifier)) {
12287 			objectName = notifier->identifier->getCStringNoCopy();
12288 		}
12289 		*thread = notifierThread;
12290 	} else {
12291 		iter = IORegistryIterator::iterateOver(
12292 			getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12293 
12294 		if (iter) {
12295 			while ((entry = iter->getNextObject())) {
12296 				node = OSDynamicCast(IOService, entry);
12297 				if (!node) {
12298 					continue;
12299 				}
12300 				if (OSDynamicCast(IOPowerConnection, node)) {
12301 					continue;
12302 				}
12303 
12304 				if (node->getBlockingDriverCall(thread, &callMethod)) {
12305 					nodeFound = true;
12306 					break;
12307 				}
12308 			}
12309 		}
12310 		if (nodeFound) {
12311 			kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12312 			if (kextName) {
12313 				objectName = kextName->getCStringNoCopy();
12314 			}
12315 		}
12316 	}
12317 	if (phaseDescription) {
12318 		strlcat(failureStr, " while ", strLen);
12319 		strlcat(failureStr, phaseDescription, strLen);
12320 		strlcat(failureStr, ".", strLen);
12321 	}
12322 	if (objectName) {
12323 		strlcat(failureStr, " Suspected bundle: ", strLen);
12324 		strlcat(failureStr, objectName, strLen);
12325 		strlcat(failureStr, ".", strLen);
12326 	}
12327 	if (*thread) {
12328 		char threadName[40];
12329 		snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12330 		strlcat(failureStr, threadName, strLen);
12331 	}
12332 
12333 	DLOG("%s\n", failureStr);
12334 }
12335 
12336 struct swd_stackshot_compressed_data {
12337 	z_output_func   zoutput;
12338 	size_t                  zipped;
12339 	uint64_t                totalbytes;
12340 	uint64_t                lastpercent;
12341 	IOReturn                error;
12342 	unsigned                outremain;
12343 	unsigned                outlen;
12344 	unsigned                writes;
12345 	Bytef *                 outbuf;
12346 };
12347 struct swd_stackshot_compressed_data swd_zip_var = { };
12348 
12349 static void *
12350 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12351 {
12352 	void *result;
12353 	LOG("Alloc in zipping %d items of size %d\n", items, size);
12354 
12355 	result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12356 	swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12357 	LOG("Offset %zu\n", swd_zs_zoffset);
12358 	return result;
12359 }
12360 
12361 static int
12362 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12363 {
12364 	unsigned len;
12365 
12366 	len = strm->avail_in;
12367 
12368 	if (len > size) {
12369 		len = size;
12370 	}
12371 	if (len == 0) {
12372 		return 0;
12373 	}
12374 
12375 	if (strm->next_in != (Bytef *) strm) {
12376 		memcpy(buf, strm->next_in, len);
12377 	} else {
12378 		bzero(buf, len);
12379 	}
12380 
12381 	strm->adler = z_crc32(strm->adler, buf, len);
12382 
12383 	strm->avail_in -= len;
12384 	strm->next_in  += len;
12385 	strm->total_in += len;
12386 
12387 	return (int)len;
12388 }
12389 
12390 static int
12391 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12392 {
12393 	unsigned int i = 0;
12394 	// if outlen > max size don't add to the buffer
12395 	assert(buf != NULL);
12396 	if (strm && buf) {
12397 		if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12398 			LOG("No space to GZIP... not writing to NVRAM\n");
12399 			return len;
12400 		}
12401 	}
12402 	for (i = 0; i < len; i++) {
12403 		*(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12404 	}
12405 	swd_zip_var.outlen += len;
12406 	return len;
12407 }
12408 
12409 static void
12410 swd_zs_free(void * __unused ref, void * __unused ptr)
12411 {
12412 }
12413 
12414 static int
12415 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12416 {
12417 	int wbits = 12;
12418 	int memlevel = 3;
12419 
12420 	if (((unsigned int) numBytes) != numBytes) {
12421 		return 0;
12422 	}
12423 
12424 	if (!swd_zs.zalloc) {
12425 		swd_zs.zalloc = swd_zs_alloc;
12426 		swd_zs.zfree = swd_zs_free;
12427 		if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12428 			// allocation failed
12429 			bzero(&swd_zs, sizeof(swd_zs));
12430 			// swd_zs_zoffset = 0;
12431 		} else {
12432 			LOG("PMRD inited the zlib allocation routines\n");
12433 		}
12434 	}
12435 
12436 	swd_zip_var.zipped = 0;
12437 	swd_zip_var.totalbytes = 0; // should this be the max that we have?
12438 	swd_zip_var.lastpercent = 0;
12439 	swd_zip_var.error = kIOReturnSuccess;
12440 	swd_zip_var.outremain = 0;
12441 	swd_zip_var.outlen = 0;
12442 	swd_zip_var.writes = 0;
12443 	swd_zip_var.outbuf = (Bytef *)outPtr;
12444 
12445 	swd_zip_var.totalbytes = numBytes;
12446 
12447 	swd_zs.avail_in = 0;
12448 	swd_zs.next_in = NULL;
12449 	swd_zs.avail_out = 0;
12450 	swd_zs.next_out = NULL;
12451 
12452 	deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12453 
12454 	z_stream *zs;
12455 	int zr;
12456 	zs = &swd_zs;
12457 
12458 	while (swd_zip_var.error >= 0) {
12459 		if (!zs->avail_in) {
12460 			zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12461 			zs->avail_in = (unsigned int) numBytes;
12462 		}
12463 		if (!zs->avail_out) {
12464 			zs->next_out = (Bytef *)zs;
12465 			zs->avail_out = UINT32_MAX;
12466 		}
12467 		zr = deflate(zs, Z_NO_FLUSH);
12468 		if (Z_STREAM_END == zr) {
12469 			break;
12470 		}
12471 		if (zr != Z_OK) {
12472 			LOG("ZERR %d\n", zr);
12473 			swd_zip_var.error = zr;
12474 		} else {
12475 			if (zs->total_in == numBytes) {
12476 				break;
12477 			}
12478 		}
12479 	}
12480 
12481 	//now flush the stream
12482 	while (swd_zip_var.error >= 0) {
12483 		if (!zs->avail_out) {
12484 			zs->next_out = (Bytef *)zs;
12485 			zs->avail_out = UINT32_MAX;
12486 		}
12487 		zr = deflate(zs, Z_FINISH);
12488 		if (Z_STREAM_END == zr) {
12489 			break;
12490 		}
12491 		if (zr != Z_OK) {
12492 			LOG("ZERR %d\n", zr);
12493 			swd_zip_var.error = zr;
12494 		} else {
12495 			if (zs->total_in == numBytes) {
12496 				LOG("Total output size %d\n", swd_zip_var.outlen);
12497 				break;
12498 			}
12499 		}
12500 	}
12501 
12502 	return swd_zip_var.outlen;
12503 }
12504 
12505 void
12506 IOPMrootDomain::deleteStackshot()
12507 {
12508 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12509 		// takeStackshot hasn't completed
12510 		return;
12511 	}
12512 	LOG("Deleting any sleepwake failure data in nvram\n");
12513 
12514 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12515 	char nvram_var_name_buf[20];
12516 	for (int i = 0; i < 8; i++) {
12517 		snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12518 		if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12519 			LOG("Removing %s returned false\n", nvram_var_name_buf);
12520 		}
12521 	}
12522 	// force NVRAM sync
12523 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12524 		DLOG("Failed to force nvram sync\n");
12525 	}
12526 	gRootDomain->swd_lock = 0;
12527 }
12528 
12529 void
12530 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12531 {
12532 	swd_hdr *                hdr = NULL;
12533 	int                      cnt = 0;
12534 	int                      max_cnt;
12535 	pid_t                    pid = 0;
12536 	kern_return_t            kr = KERN_SUCCESS;
12537 	uint64_t                 flags;
12538 
12539 	char *                   dstAddr;
12540 	uint32_t                 size;
12541 	uint32_t                 bytesRemaining;
12542 	unsigned                 bytesWritten = 0;
12543 
12544 	char                     failureStr[512];
12545 	thread_t                 thread = NULL;
12546 	const char *             swfPanic = "swfPanic";
12547 
12548 	uint32_t                 bufSize;
12549 	int                      success = 0;
12550 
12551 #if defined(__i386__) || defined(__x86_64__)
12552 	const bool               concise = false;
12553 #else
12554 	const bool               concise = true;
12555 #endif
12556 
12557 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12558 		return;
12559 	}
12560 
12561 	failureStr[0] = 0;
12562 	if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12563 		return;
12564 	}
12565 
12566 	if (wdogTrigger) {
12567 		getFailureData(&thread, failureStr, sizeof(failureStr));
12568 
12569 		if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12570 			goto skip_stackshot;
12571 		}
12572 	} else {
12573 		AbsoluteTime now;
12574 		uint64_t nsec;
12575 		clock_get_uptime(&now);
12576 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12577 		absolutetime_to_nanoseconds(now, &nsec);
12578 		snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12579 	}
12580 
12581 	if (swd_buffer == NULL) {
12582 		sleepWakeDebugMemAlloc();
12583 		if (swd_buffer == NULL) {
12584 			return;
12585 		}
12586 	}
12587 	hdr = (swd_hdr *)swd_buffer;
12588 	bufSize = hdr->alloc_size;
12589 
12590 	dstAddr = (char*)hdr + hdr->spindump_offset;
12591 	flags = STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_THREAD_WAITINFO | STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12592 
12593 	/* If not wdogTrigger only take kernel tasks stackshot
12594 	 */
12595 	if (wdogTrigger) {
12596 		pid = -1;
12597 		max_cnt = 3;
12598 	} else {
12599 		pid = 0;
12600 		max_cnt = 2;
12601 	}
12602 
12603 	/* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12604 	 * If we run out of space, take stackshot with only kernel task
12605 	 */
12606 	while (success == 0 && cnt < max_cnt) {
12607 		bytesRemaining = bufSize - hdr->spindump_offset;
12608 		cnt++;
12609 		DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12610 
12611 		size = bytesRemaining;
12612 		kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12613 		DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12614 		    kr, pid, size, flags, bytesWritten);
12615 		if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12616 			if (pid == -1) {
12617 				pid = 0;
12618 			} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12619 				flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12620 			} else {
12621 				LOG("Insufficient buffer size for only kernel task\n");
12622 				break;
12623 			}
12624 		}
12625 		if (kr == KERN_SUCCESS) {
12626 			if (bytesWritten == 0) {
12627 				MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12628 				continue;
12629 			}
12630 			bytesRemaining -= bytesWritten;
12631 			hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12632 
12633 			memset(hdr->reason, 0x20, sizeof(hdr->reason));
12634 
12635 			// Compress stackshot and save to NVRAM
12636 			{
12637 				char *outbuf = (char *)swd_compressed_buffer;
12638 				int outlen = 0;
12639 				int num_chunks = 0;
12640 				int max_chunks = 0;
12641 				int leftover = 0;
12642 				char nvram_var_name_buffer[20];
12643 
12644 				outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12645 
12646 				if (outlen) {
12647 					max_chunks = outlen / (2096 - 200);
12648 					leftover = outlen % (2096 - 200);
12649 
12650 					if (max_chunks < 8) {
12651 						for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12652 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12653 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12654 								LOG("Failed to update NVRAM %d\n", num_chunks);
12655 								break;
12656 							}
12657 						}
12658 						if (leftover) {
12659 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12660 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12661 								LOG("Failed to update NVRAM with leftovers\n");
12662 							}
12663 						}
12664 						success = 1;
12665 						LOG("Successfully saved stackshot to NVRAM\n");
12666 					} else {
12667 						if (pid == -1) {
12668 							LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12669 							pid = 0;
12670 						} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12671 							LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12672 							flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12673 						} else {
12674 							LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12675 							break;
12676 						}
12677 					}
12678 				}
12679 			}
12680 		}
12681 	}
12682 
12683 	if (failureStr[0]) {
12684 		// append sleep-wake failure code
12685 		char traceCode[80];
12686 		snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12687 		    pmTracer->getTraceData(), pmTracer->getTracePhase());
12688 		strlcat(failureStr, traceCode, sizeof(failureStr));
12689 		if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12690 			DLOG("Failed to write SleepWake failure string\n");
12691 		}
12692 	}
12693 
12694 	// force NVRAM sync
12695 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12696 		DLOG("Failed to force nvram sync\n");
12697 	}
12698 
12699 skip_stackshot:
12700 	if (wdogTrigger) {
12701 		if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12702 			if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12703 				// If current boot is due to this watch dog trigger restart in previous boot,
12704 				// then don't trigger again until at least 1 successful sleep & wake.
12705 				if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12706 					LOG("Shutting down due to repeated Sleep/Wake failures\n");
12707 					updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12708 					PEHaltRestart(kPEHaltCPU);
12709 					return;
12710 				}
12711 			}
12712 			if (gSwdPanic == 0) {
12713 				LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12714 				updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12715 				PEHaltRestart(kPERestartCPU);
12716 			}
12717 		}
12718 		if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12719 			DLOG("Failed to write SleepWake failure panic key\n");
12720 		}
12721 #if defined(__x86_64__)
12722 		if (thread) {
12723 			panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12724 		} else
12725 #endif /* defined(__x86_64__) */
12726 		{
12727 			panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12728 		}
12729 	} else {
12730 		gRootDomain->swd_lock = 0;
12731 		return;
12732 	}
12733 }
12734 
12735 void
12736 IOPMrootDomain::sleepWakeDebugMemAlloc()
12737 {
12738 	vm_size_t    size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12739 
12740 	swd_hdr      *hdr = NULL;
12741 	void         *bufPtr = NULL;
12742 
12743 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12744 
12745 
12746 	if (kIOSleepWakeWdogOff & gIOKitDebug) {
12747 		return;
12748 	}
12749 
12750 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12751 		return;
12752 	}
12753 
12754 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12755 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12756 		size);
12757 	if (memDesc == NULL) {
12758 		DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12759 		goto exit;
12760 	}
12761 
12762 	bufPtr = memDesc->getBytesNoCopy();
12763 
12764 	// Carve out memory for zlib routines
12765 	swd_zs_zmem = (vm_offset_t)bufPtr;
12766 	bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12767 
12768 	// Carve out memory for compressed stackshots
12769 	swd_compressed_buffer = bufPtr;
12770 	bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12771 
12772 	// Remaining is used for holding stackshot
12773 	hdr = (swd_hdr *)bufPtr;
12774 	memset(hdr, 0, sizeof(swd_hdr));
12775 
12776 	hdr->signature = SWD_HDR_SIGNATURE;
12777 	hdr->alloc_size = SWD_STACKSHOT_SIZE;
12778 
12779 	hdr->spindump_offset = sizeof(swd_hdr);
12780 	swd_buffer = (void *)hdr;
12781 	swd_memDesc = os::move(memDesc);
12782 	DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12783 
12784 exit:
12785 	gRootDomain->swd_lock = 0;
12786 }
12787 
12788 void
12789 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12790 {
12791 #if UNUSED
12792 	vm_size_t    size = SWD_SPINDUMP_SIZE;
12793 
12794 	swd_hdr      *hdr = NULL;
12795 
12796 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12797 
12798 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12799 		return;
12800 	}
12801 
12802 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12803 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12804 		SWD_SPINDUMP_SIZE);
12805 
12806 	if (memDesc == NULL) {
12807 		DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12808 		goto exit;
12809 	}
12810 
12811 
12812 	hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12813 	memset(hdr, 0, sizeof(swd_hdr));
12814 
12815 	hdr->signature = SWD_HDR_SIGNATURE;
12816 	hdr->alloc_size = size;
12817 
12818 	hdr->spindump_offset = sizeof(swd_hdr);
12819 	swd_spindump_buffer = (void *)hdr;
12820 	swd_spindump_memDesc = os::move(memDesc);
12821 
12822 exit:
12823 	gRootDomain->swd_lock = 0;
12824 #endif /* UNUSED */
12825 }
12826 
12827 void
12828 IOPMrootDomain::sleepWakeDebugEnableWdog()
12829 {
12830 }
12831 
12832 bool
12833 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12834 {
12835 	return !systemBooting && !systemShutdown && !gWillShutdown;
12836 }
12837 
12838 void
12839 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12840 {
12841 	swd_hdr *hdr = NULL;
12842 	errno_t error = EIO;
12843 
12844 	if (swd_spindump_buffer && gSpinDumpBufferFull) {
12845 		hdr = (swd_hdr *)swd_spindump_buffer;
12846 
12847 		error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12848 		    (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12849 
12850 		if (error) {
12851 			return;
12852 		}
12853 
12854 		sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12855 		    (char*)hdr + offsetof(swd_hdr, UUID),
12856 		    sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12857 
12858 		gSpinDumpBufferFull = false;
12859 	}
12860 }
12861 
12862 errno_t
12863 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12864 {
12865 	struct vnode         *vp = NULL;
12866 	vfs_context_t        ctx = vfs_context_create(vfs_context_current());
12867 	kauth_cred_t         cred = vfs_context_ucred(ctx);
12868 	struct vnode_attr    va;
12869 	errno_t      error = EIO;
12870 
12871 	if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12872 	    S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12873 		LOG("Failed to open the file %s\n", name);
12874 		swd_flags |= SWD_FILEOP_ERROR;
12875 		goto exit;
12876 	}
12877 	VATTR_INIT(&va);
12878 	VATTR_WANTED(&va, va_nlink);
12879 	/* Don't dump to non-regular files or files with links. */
12880 	if (vp->v_type != VREG ||
12881 	    vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12882 		LOG("Bailing as this is not a regular file\n");
12883 		swd_flags |= SWD_FILEOP_ERROR;
12884 		goto exit;
12885 	}
12886 	VATTR_INIT(&va);
12887 	VATTR_SET(&va, va_data_size, 0);
12888 	vnode_setattr(vp, &va, ctx);
12889 
12890 
12891 	if (buf != NULL) {
12892 		error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12893 		    UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12894 		if (error != 0) {
12895 			LOG("Failed to save sleep wake log. err 0x%x\n", error);
12896 			swd_flags |= SWD_FILEOP_ERROR;
12897 		} else {
12898 			DLOG("Saved %d bytes to file %s\n", len, name);
12899 		}
12900 	}
12901 
12902 exit:
12903 	if (vp) {
12904 		vnode_close(vp, FWRITE, ctx);
12905 	}
12906 	if (ctx) {
12907 		vfs_context_rele(ctx);
12908 	}
12909 
12910 	return error;
12911 }
12912 
12913 #else /* defined(__i386__) || defined(__x86_64__) */
12914 
12915 void
12916 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12917 {
12918 	if (restart) {
12919 		if (gSwdPanic == 0) {
12920 			return;
12921 		}
12922 		panic("Sleep/Wake hang detected");
12923 		return;
12924 	}
12925 }
12926 
12927 void
12928 IOPMrootDomain::takeStackshot(bool restart)
12929 {
12930 #pragma unused(restart)
12931 }
12932 
12933 void
12934 IOPMrootDomain::deleteStackshot()
12935 {
12936 }
12937 
12938 void
12939 IOPMrootDomain::sleepWakeDebugMemAlloc()
12940 {
12941 }
12942 
12943 void
12944 IOPMrootDomain::saveFailureData2File()
12945 {
12946 }
12947 
12948 void
12949 IOPMrootDomain::sleepWakeDebugEnableWdog()
12950 {
12951 }
12952 
12953 bool
12954 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12955 {
12956 	return false;
12957 }
12958 
12959 void
12960 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12961 {
12962 }
12963 
12964 errno_t
12965 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12966 {
12967 	return 0;
12968 }
12969 
12970 #endif /* defined(__i386__) || defined(__x86_64__) */
12971 
12972