xref: /xnu-11417.101.15/iokit/Kernel/IOPMrootDomain.cpp (revision e3723e1f17661b24996789d8afc084c0c3303b26)
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 (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7523 			break; // always sleep on low battery or when in thermal warning/emergency state
7524 		}
7525 
7526 		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7527 			break; // always sleep on dark wake thermal emergencies
7528 		}
7529 
7530 		if (preventSystemSleepList->getCount() != 0) {
7531 			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7532 			break;
7533 		}
7534 
7535 		if (_driverKitMatchingAssertionCount != 0) {
7536 			err = kPMCPUAssertion;
7537 			break;
7538 		}
7539 
7540 		// Check for any dexts currently being added to the PM tree. Sleeping while
7541 		// this is in flight can cause IOServicePH to timeout.
7542 		if (!IOServicePH::checkPMReady()) {
7543 #if !defined(XNU_TARGET_OS_OSX)
7544 			// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7545 			// in dark wake for long periods of time, which causes issues as apps were
7546 			// already informed of sleep during the f->9 transition. As a temporary
7547 			// measure, always full wake if we hit this specific condition.
7548 			pmPowerStateQueue->submitPowerEvent(
7549 				kPowerEventPolicyStimulus,
7550 				(void *) kStimulusDarkWakeActivityTickle);
7551 #endif
7552 			err = kPMDKNotReady;
7553 			break;
7554 		}
7555 
7556 		if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7557 		    kIOPMDriverAssertionLevelOn) {
7558 			err = kPMCPUAssertion; // 5. CPU assertion
7559 			break;
7560 		}
7561 
7562 		if (pciCantSleepValid) {
7563 			if (pciCantSleepFlag) {
7564 				err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7565 			}
7566 			break;
7567 		} else if (sleepSupportedPEFunction &&
7568 		    CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7569 			IOReturn ret;
7570 			OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7571 			ret = getPlatform()->callPlatformFunction(
7572 				sleepSupportedPEFunction.get(), false,
7573 				NULL, NULL, NULL, NULL);
7574 			pciCantSleepValid = true;
7575 			pciCantSleepFlag  = false;
7576 			if ((platformSleepSupport & kPCICantSleep) ||
7577 			    ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7578 				err = 6; // 6. PCI card does not support PM
7579 				pciCantSleepFlag = true;
7580 				break;
7581 			}
7582 		}
7583 	}while (false);
7584 
7585 	if (err) {
7586 		DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7587 		return false;
7588 	}
7589 	return true;
7590 }
7591 
7592 bool
7593 IOPMrootDomain::checkSystemSleepEnabled( void )
7594 {
7595 	return checkSystemSleepAllowed(0, 0);
7596 }
7597 
7598 bool
7599 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7600 {
7601 	ASSERT_GATED();
7602 	return checkSystemSleepAllowed(1, sleepReason);
7603 }
7604 
7605 //******************************************************************************
7606 // checkSystemCanSustainFullWake
7607 //******************************************************************************
7608 
7609 bool
7610 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7611 {
7612 	if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7613 		// Low battery wake, or received a low battery notification
7614 		// while system is awake. This condition will persist until
7615 		// the following wake.
7616 		return false;
7617 	}
7618 
7619 	if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7620 		// Graphics state is unknown and external display might not be probed.
7621 		// Do not incorporate state that requires graphics to be in max power
7622 		// such as desktopMode or clamshellDisabled.
7623 
7624 		if (!acAdaptorConnected) {
7625 			DLOG("full wake check: no AC\n");
7626 			return false;
7627 		}
7628 	}
7629 	return true;
7630 }
7631 
7632 //******************************************************************************
7633 // checkSystemCanAbortIdleSleep
7634 //******************************************************************************
7635 
7636 bool
7637 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7638 {
7639 	bool abortableSleepType =  ((lastSleepReason == kIOPMSleepReasonIdle)
7640 	    || (lastSleepReason == 0));
7641 	return idleSleepRevertible && abortableSleepType;
7642 }
7643 
7644 //******************************************************************************
7645 // attemptIdleSleepAbort
7646 //******************************************************************************
7647 
7648 bool
7649 IOPMrootDomain::attemptIdleSleepAbort( void )
7650 {
7651 	if (!gIOPMWorkLoop->inGate()) {
7652 		bool ret = gIOPMWorkLoop->runAction(
7653 			OSMemberFunctionCast(IOWorkLoop::Action, this,
7654 			&IOPMrootDomain::attemptIdleSleepAbort),
7655 			this);
7656 		return ret;
7657 	}
7658 
7659 	bool canAbort = checkSystemCanAbortIdleSleep();
7660 	if (canAbort) {
7661 		cancelIdlePowerDownSync();
7662 	} else if (lastSleepReason == kIOPMSleepReasonIdle) {
7663 		scheduleImmediateDebugWake();
7664 	}
7665 
7666 	return canAbort;
7667 }
7668 
7669 //******************************************************************************
7670 // setIdleSleepRevertible
7671 //******************************************************************************
7672 
7673 void
7674 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7675 {
7676 	idleSleepRevertible = revertible;
7677 }
7678 
7679 //******************************************************************************
7680 // mustHibernate
7681 //******************************************************************************
7682 
7683 #if HIBERNATION
7684 
7685 bool
7686 IOPMrootDomain::mustHibernate( void )
7687 {
7688 	return lowBatteryCondition || thermalWarningState;
7689 }
7690 
7691 #endif /* HIBERNATION */
7692 
7693 //******************************************************************************
7694 // AOT
7695 //******************************************************************************
7696 
7697 // Tables for accumulated days in year by month, latter used for leap years
7698 
7699 static const unsigned int daysbymonth[] =
7700 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7701 
7702 static const unsigned int lydaysbymonth[] =
7703 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7704 
7705 static int __unused
7706 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7707 {
7708 	const unsigned int *    dbm = daysbymonth;
7709 	clock_sec_t             n, x, y, z;
7710 
7711 	// Calculate seconds, minutes and hours
7712 
7713 	n = secs % (24 * 3600);
7714 	dt->second = n % 60;
7715 	n /= 60;
7716 	dt->minute = n % 60;
7717 	dt->hour = (typeof(dt->hour))(n / 60);
7718 
7719 	// Calculate day of week
7720 
7721 	n = secs / (24 * 3600);
7722 //	dt->dayWeek = (n + 4) % 7;
7723 
7724 	// Calculate year
7725 	// Rebase from days since Unix epoch (1/1/1970) store in 'n',
7726 	// to days since 1/1/1968 to start on 4 year cycle, beginning
7727 	// on a leap year.
7728 
7729 	n += (366 + 365);
7730 
7731 	// Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7732 	// Valid before 2100, since 2100 is not a leap year.
7733 
7734 	x = n / 1461;       // number of 4 year cycles
7735 	y = n % 1461;       // days into current 4 year cycle
7736 	z = 1968 + (4 * x);
7737 
7738 	// Add in years in the current 4 year cycle
7739 
7740 	if (y >= 366) {
7741 		y -= 366;   // days after the leap year
7742 		n = y % 365; // days into the current year
7743 		z += (1 + y / 365); // years after the past 4-yr cycle
7744 	} else {
7745 		n = y;
7746 		dbm = lydaysbymonth;
7747 	}
7748 	if (z > 2099) {
7749 		return 0;
7750 	}
7751 
7752 	dt->year = (typeof(dt->year))z;
7753 
7754 	// Adjust remaining days value to start at 1
7755 
7756 	n += 1;
7757 
7758 	// Calculate month
7759 
7760 	for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7761 		continue;
7762 	}
7763 	dt->month = (typeof(dt->month))x;
7764 
7765 	// Calculate day of month
7766 
7767 	dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7768 
7769 	return 1;
7770 }
7771 
7772 static clock_sec_t
7773 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7774 {
7775 	const unsigned int *    dbm = daysbymonth;
7776 	long                    y, secs, days;
7777 
7778 	if (dt->year < 1970 || dt->month > 12) {
7779 		return 0;
7780 	}
7781 
7782 	// Seconds elapsed in the current day
7783 
7784 	secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7785 
7786 	// Number of days from 1/1/70 to beginning of current year
7787 	// Account for extra day every 4 years starting at 1973
7788 
7789 	y = dt->year - 1970;
7790 	days = (y * 365) + ((y + 1) / 4);
7791 
7792 	// Change table if current year is a leap year
7793 
7794 	if ((dt->year % 4) == 0) {
7795 		dbm = lydaysbymonth;
7796 	}
7797 
7798 	// Add in days elapsed in the current year
7799 
7800 	days += (dt->day - 1) + dbm[dt->month - 1];
7801 
7802 	// Add accumulated days to accumulated seconds
7803 
7804 	secs += 24 * 3600 * days;
7805 
7806 	return secs;
7807 }
7808 
7809 unsigned long
7810 IOPMrootDomain::getRUN_STATE(void)
7811 {
7812 	return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7813 }
7814 
7815 bool
7816 IOPMrootDomain::isAOTMode()
7817 {
7818 	return _aotNow;
7819 }
7820 
7821 IOReturn
7822 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7823 {
7824 	clock_sec_t     nowsecs, wakesecs;
7825 	clock_usec_t    nowmicrosecs, wakemicrosecs;
7826 	uint64_t        nowAbs, wakeAbs;
7827 
7828 	if (!_aotMode) {
7829 		return kIOReturnNotReady;
7830 	}
7831 
7832 	clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7833 	wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7834 	if (wakeAbs < nowAbs) {
7835 		printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7836 		wakeAbs = nowAbs;
7837 	}
7838 	wakeAbs -= nowAbs;
7839 	absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7840 
7841 	wakesecs += nowsecs;
7842 	wakemicrosecs += nowmicrosecs;
7843 	if (wakemicrosecs >= USEC_PER_SEC) {
7844 		wakesecs++;
7845 		wakemicrosecs -= USEC_PER_SEC;
7846 	}
7847 	if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7848 		wakesecs++;
7849 	}
7850 
7851 	IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7852 
7853 	if (_aotWakeTimeContinuous != wakeContinuousTime) {
7854 		_aotWakeTimeContinuous = wakeContinuousTime;
7855 		IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7856 	}
7857 	_aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7858 	_aotWakeTimeUTC               = wakesecs;
7859 
7860 	return kIOReturnSuccess;
7861 }
7862 
7863 // assumes WAKEEVENT_LOCK
7864 bool
7865 IOPMrootDomain::aotShouldExit(bool software)
7866 {
7867 	bool exitNow = false;
7868 	const char * reason = "";
7869 
7870 	if (!_aotNow) {
7871 		return false;
7872 	}
7873 
7874 	if (software) {
7875 		exitNow = true;
7876 		_aotMetrics->softwareRequestCount++;
7877 		reason = "software request";
7878 	} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7879 		exitNow = true;
7880 		reason = gWakeReasonString;
7881 	} else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7882 		clock_sec_t     sec;
7883 		clock_usec_t    usec;
7884 		clock_get_calendar_microtime(&sec, &usec);
7885 		if (_calendarWakeAlarmUTC <= sec) {
7886 			exitNow = true;
7887 			_aotMetrics->rtcAlarmsCount++;
7888 			reason = "user alarm";
7889 		}
7890 	}
7891 	if (exitNow) {
7892 		_aotPendingFlags |= kIOPMWakeEventAOTExit;
7893 		IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7894 		    reason,
7895 		    _aotMetrics->sleepCount,
7896 		    _aotMetrics->possibleCount,
7897 		    _aotMetrics->confirmedPossibleCount,
7898 		    _aotMetrics->rejectedPossibleCount,
7899 		    _aotMetrics->expiredPossibleCount,
7900 		    _aotMetrics->noTimeSetCount,
7901 		    _aotMetrics->rtcAlarmsCount);
7902 	}
7903 	return exitNow;
7904 }
7905 
7906 void
7907 IOPMrootDomain::aotExit(bool cps)
7908 {
7909 	uint32_t savedMessageMask;
7910 
7911 	ASSERT_GATED();
7912 	_aotNow = false;
7913 	_aotReadyToFullWake = false;
7914 	if (_aotTimerScheduled) {
7915 		_aotTimerES->cancelTimeout();
7916 		_aotTimerScheduled = false;
7917 	}
7918 	updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7919 
7920 	_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7921 	_aotLastWakeTime = 0;
7922 	if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7923 		WAKEEVENT_LOCK();
7924 		strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7925 		    gWakeReasonString,
7926 		    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7927 		WAKEEVENT_UNLOCK();
7928 	}
7929 
7930 	_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7931 
7932 	// Preserve the message mask since a system wake transition
7933 	// may have already started and initialized the mask.
7934 	savedMessageMask = _systemMessageClientMask;
7935 	_systemMessageClientMask = kSystemMessageClientLegacyApp;
7936 	tellClients(kIOMessageSystemWillPowerOn);
7937 	_systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7938 
7939 	if (cps) {
7940 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7941 	}
7942 }
7943 
7944 void
7945 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7946 {
7947 	bool exitNow;
7948 
7949 	IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7950 
7951 	WAKEEVENT_LOCK();
7952 	exitNow = aotShouldExit(false);
7953 	if (timer != NULL) {
7954 		_aotTimerScheduled = false;
7955 	}
7956 	WAKEEVENT_UNLOCK();
7957 	if (exitNow) {
7958 		aotExit(true);
7959 	} else {
7960 #if 0
7961 		if (_aotLingerTime) {
7962 			uint64_t deadline;
7963 			IOLog("aot linger before sleep\n");
7964 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7965 			clock_delay_until(deadline);
7966 		}
7967 #endif
7968 		privateSleepSystem(kIOPMSleepReasonSoftware);
7969 	}
7970 }
7971 
7972 //******************************************************************************
7973 // adjustPowerState
7974 //
7975 // Conditions that affect our wake/sleep decision has changed.
7976 // If conditions dictate that the system must remain awake, clamp power
7977 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7978 // is TRUE, then remove the power clamp and allow the power state to drop
7979 // to SLEEP_STATE.
7980 //******************************************************************************
7981 
7982 void
7983 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7984 {
7985 	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7986 	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7987 
7988 	ASSERT_GATED();
7989 
7990 	if (_aotNow) {
7991 		bool exitNow;
7992 
7993 		if (AOT_STATE != getPowerState()) {
7994 			return;
7995 		}
7996 		WAKEEVENT_LOCK();
7997 		exitNow = aotShouldExit(false);
7998 		if (!exitNow
7999 		    && !_aotTimerScheduled
8000 		    && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8001 			_aotTimerScheduled = true;
8002 			if (_aotLingerTime) {
8003 				_aotTimerES->setTimeout(_aotLingerTime);
8004 			} else {
8005 				_aotTimerES->setTimeout(800, kMillisecondScale);
8006 			}
8007 		}
8008 		WAKEEVENT_UNLOCK();
8009 		if (exitNow) {
8010 			aotExit(true);
8011 		} else {
8012 			_aotReadyToFullWake = true;
8013 			if (!_aotTimerScheduled) {
8014 				if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8015 					// Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8016 					// Doing so will result in the sleep being cancelled anyway,
8017 					// but this check avoids unnecessary thrashing in the power state engine.
8018 					return;
8019 				}
8020 				privateSleepSystem(kIOPMSleepReasonSoftware);
8021 			}
8022 		}
8023 		return;
8024 	}
8025 
8026 	if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8027 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8028 	} else if (sleepASAP) {
8029 		changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8030 	}
8031 }
8032 
8033 void
8034 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8035 {
8036 	if (powerOn) {
8037 		if (!checkSystemCanSustainFullWake()) {
8038 			DLOG("System cannot sustain full wake\n");
8039 			return;
8040 		}
8041 
8042 		// Force wrangler to max power state. If system is in dark wake
8043 		// this alone won't raise the wrangler's power state.
8044 		if (wrangler) {
8045 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8046 		}
8047 
8048 		// System in dark wake, always requesting full wake should
8049 		// not have any bad side-effects, even if the request fails.
8050 
8051 		if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8052 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8053 			requestFullWake( kFullWakeReasonDisplayOn );
8054 		}
8055 	} else {
8056 		// Relenquish desire to power up display.
8057 		// Must first transition to state 1 since wrangler doesn't
8058 		// power off the displays at state 0. At state 0 the root
8059 		// domain is removed from the wrangler's power client list.
8060 		if (wrangler) {
8061 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8062 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8063 		}
8064 	}
8065 }
8066 
8067 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8068 
8069 //******************************************************************************
8070 // dispatchPowerEvent
8071 //
8072 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8073 //******************************************************************************
8074 
8075 void
8076 IOPMrootDomain::dispatchPowerEvent(
8077 	uint32_t event, void * arg0, uint64_t arg1 )
8078 {
8079 	ASSERT_GATED();
8080 
8081 	switch (event) {
8082 	case kPowerEventFeatureChanged:
8083 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8084 		messageClients(kIOPMMessageFeatureChange, this);
8085 		break;
8086 
8087 	case kPowerEventReceivedPowerNotification:
8088 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8089 		handlePowerNotification((UInt32)(uintptr_t) arg0 );
8090 		break;
8091 
8092 	case kPowerEventSystemBootCompleted:
8093 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8094 		if (systemBooting) {
8095 			systemBooting = false;
8096 
8097 			if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8098 				DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8099 				if (test_sleep_in_vm && gSleepDisabledFlag) {
8100 					DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8101 					gSleepDisabledFlag = 0;
8102 				}
8103 			}
8104 
8105 			if (lowBatteryCondition || thermalEmergencyState) {
8106 				if (lowBatteryCondition) {
8107 					privateSleepSystem(kIOPMSleepReasonLowPower);
8108 				} else {
8109 					privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8110 				}
8111 				// The rest is unnecessary since the system is expected
8112 				// to sleep immediately. The following wake will update
8113 				// everything.
8114 				break;
8115 			}
8116 
8117 			sleepWakeDebugMemAlloc();
8118 			saveFailureData2File();
8119 
8120 			// If lid is closed, re-send lid closed notification
8121 			// now that booting is complete.
8122 			if (clamshellClosed) {
8123 				handlePowerNotification(kLocalEvalClamshellCommand);
8124 			}
8125 			evaluatePolicy( kStimulusAllowSystemSleepChanged );
8126 		}
8127 		break;
8128 
8129 	case kPowerEventSystemShutdown:
8130 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8131 		if (kOSBooleanTrue == (OSBoolean *) arg0) {
8132 			/* We set systemShutdown = true during shutdown
8133 			 *  to prevent sleep at unexpected times while loginwindow is trying
8134 			 *  to shutdown apps and while the OS is trying to transition to
8135 			 *  complete power of.
8136 			 *
8137 			 *  Set to true during shutdown, as soon as loginwindow shows
8138 			 *  the "shutdown countdown dialog", through individual app
8139 			 *  termination, and through black screen kernel shutdown.
8140 			 */
8141 			systemShutdown = true;
8142 		} else {
8143 			/*
8144 			 *  A shutdown was initiated, but then the shutdown
8145 			 *  was cancelled, clearing systemShutdown to false here.
8146 			 */
8147 			systemShutdown = false;
8148 		}
8149 		break;
8150 
8151 	case kPowerEventUserDisabledSleep:
8152 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8153 		userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8154 		break;
8155 
8156 	case kPowerEventRegisterSystemCapabilityClient:
8157 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8158 
8159 		// reset() handles the arg0 == nullptr case for us
8160 		systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8161 		/* intentional fall-through */
8162 		[[clang::fallthrough]];
8163 
8164 	case kPowerEventRegisterKernelCapabilityClient:
8165 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8166 		if (!_joinedCapabilityClients) {
8167 			_joinedCapabilityClients = OSSet::withCapacity(8);
8168 		}
8169 		if (arg0) {
8170 			OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8171 			if (_joinedCapabilityClients) {
8172 				_joinedCapabilityClients->setObject(notify.get());
8173 				synchronizePowerTree( kIOPMSyncNoChildNotify );
8174 			}
8175 		}
8176 		break;
8177 
8178 	case kPowerEventPolicyStimulus:
8179 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8180 		if (arg0) {
8181 			int stimulus = (int)(uintptr_t) arg0;
8182 			evaluatePolicy(stimulus, (uint32_t) arg1);
8183 		}
8184 		break;
8185 
8186 	case kPowerEventAssertionCreate:
8187 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8188 		if (pmAssertions) {
8189 			pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8190 		}
8191 		break;
8192 
8193 
8194 	case kPowerEventAssertionRelease:
8195 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8196 		if (pmAssertions) {
8197 			pmAssertions->handleReleaseAssertion(arg1);
8198 		}
8199 		break;
8200 
8201 	case kPowerEventAssertionSetLevel:
8202 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8203 		if (pmAssertions) {
8204 			pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8205 		}
8206 		break;
8207 
8208 	case kPowerEventQueueSleepWakeUUID:
8209 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8210 		handleQueueSleepWakeUUID((OSObject *)arg0);
8211 		break;
8212 	case kPowerEventPublishSleepWakeUUID:
8213 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8214 		handlePublishSleepWakeUUID((bool)arg0);
8215 		break;
8216 
8217 	case kPowerEventSetDisplayPowerOn:
8218 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8219 		if (arg1 != 0) {
8220 			displayPowerOnRequested = true;
8221 		} else {
8222 			displayPowerOnRequested = false;
8223 		}
8224 		handleSetDisplayPowerOn(displayPowerOnRequested);
8225 		break;
8226 
8227 	case kPowerEventPublishWakeType:
8228 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8229 
8230 		// Don't replace wake type property if already set
8231 		if ((arg0 == gIOPMWakeTypeUserKey) ||
8232 		    !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8233 			const char * wakeType = NULL;
8234 
8235 			if (arg0 == gIOPMWakeTypeUserKey) {
8236 				requestUserActive(this, "WakeTypeUser");
8237 				wakeType = kIOPMRootDomainWakeTypeUser;
8238 			} else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8239 				if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8240 					requestUserActive(this, "WakeTypeAlarm");
8241 				}
8242 				wakeType = kIOPMRootDomainWakeTypeAlarm;
8243 			} else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8244 				darkWakeSleepService = true;
8245 				wakeType = kIOPMRootDomainWakeTypeSleepService;
8246 			} else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8247 				wakeType = kIOPMRootDomainWakeTypeMaintenance;
8248 			}
8249 
8250 			if (wakeType) {
8251 				setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8252 			}
8253 		}
8254 		break;
8255 
8256 	case kPowerEventAOTEvaluate:
8257 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8258 		if (_aotReadyToFullWake) {
8259 			aotEvaluate(NULL);
8260 		}
8261 		break;
8262 	}
8263 }
8264 
8265 //******************************************************************************
8266 // systemPowerEventOccurred
8267 //
8268 // The power controller is notifying us of a hardware-related power management
8269 // event that we must handle.
8270 //
8271 // systemPowerEventOccurred covers the same functionality that
8272 // receivePowerNotification does; it simply provides a richer API for conveying
8273 // more information.
8274 //******************************************************************************
8275 
8276 IOReturn
8277 IOPMrootDomain::systemPowerEventOccurred(
8278 	const OSSymbol *event,
8279 	uint32_t intValue)
8280 {
8281 	IOReturn        attempt = kIOReturnSuccess;
8282 	OSSharedPtr<OSNumber>        newNumber;
8283 
8284 	if (!event) {
8285 		return kIOReturnBadArgument;
8286 	}
8287 
8288 	newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8289 	if (!newNumber) {
8290 		return kIOReturnInternalError;
8291 	}
8292 
8293 	attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8294 
8295 	return attempt;
8296 }
8297 
8298 void
8299 IOPMrootDomain::setThermalState(OSObject *value)
8300 {
8301 	OSNumber * num;
8302 
8303 	if (gIOPMWorkLoop->inGate() == false) {
8304 		gIOPMWorkLoop->runAction(
8305 			OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8306 			(OSObject *)this,
8307 			(void *)value);
8308 
8309 		return;
8310 	}
8311 	if (value && (num = OSDynamicCast(OSNumber, value))) {
8312 		thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8313 		    (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8314 	}
8315 }
8316 
8317 IOReturn
8318 IOPMrootDomain::systemPowerEventOccurred(
8319 	const OSSymbol *event,
8320 	OSObject *value)
8321 {
8322 	OSSharedPtr<OSDictionary> thermalsDict;
8323 	bool shouldUpdate = true;
8324 
8325 	if (!event || !value) {
8326 		return kIOReturnBadArgument;
8327 	}
8328 
8329 	// LOCK
8330 	// We reuse featuresDict Lock because it already exists and guards
8331 	// the very infrequently used publish/remove feature mechanism; so there's zero rsk
8332 	// of stepping on that lock.
8333 	if (featuresDictLock) {
8334 		IOLockLock(featuresDictLock);
8335 	}
8336 
8337 	OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8338 	OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8339 
8340 	if (origThermalsDict) {
8341 		thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8342 	} else {
8343 		thermalsDict = OSDictionary::withCapacity(1);
8344 	}
8345 
8346 	if (!thermalsDict) {
8347 		shouldUpdate = false;
8348 		goto exit;
8349 	}
8350 
8351 	thermalsDict->setObject(event, value);
8352 
8353 	setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8354 
8355 exit:
8356 	// UNLOCK
8357 	if (featuresDictLock) {
8358 		IOLockUnlock(featuresDictLock);
8359 	}
8360 
8361 	if (shouldUpdate) {
8362 		if (event &&
8363 		    event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8364 			setThermalState(value);
8365 		}
8366 		messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8367 	}
8368 
8369 	return kIOReturnSuccess;
8370 }
8371 
8372 //******************************************************************************
8373 // receivePowerNotification
8374 //
8375 // The power controller is notifying us of a hardware-related power management
8376 // event that we must handle. This may be a result of an 'environment' interrupt
8377 // from the power mgt micro.
8378 //******************************************************************************
8379 
8380 IOReturn
8381 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8382 {
8383 	if (msg & kIOPMPowerButton) {
8384 		uint32_t currentPhase = pmTracer->getTracePhase();
8385 		if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8386 			DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8387 			swd_flags |= SWD_PWR_BTN_STACKSHOT;
8388 			thread_call_enter(powerButtonDown);
8389 		} else {
8390 			DEBUG_LOG("power button pressed when system is up\n");
8391 		}
8392 	} else if (msg & kIOPMPowerButtonUp) {
8393 		if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8394 			swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8395 			thread_call_enter(powerButtonUp);
8396 		}
8397 	} else {
8398 		pmPowerStateQueue->submitPowerEvent(
8399 			kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8400 	}
8401 	return kIOReturnSuccess;
8402 }
8403 
8404 void
8405 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8406 {
8407 	bool        eval_clamshell = false;
8408 	bool        eval_clamshell_alarm = false;
8409 
8410 	ASSERT_GATED();
8411 
8412 	/*
8413 	 * Local (IOPMrootDomain only) eval clamshell command
8414 	 */
8415 	if (msg & kLocalEvalClamshellCommand) {
8416 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8417 			eval_clamshell_alarm = true;
8418 
8419 			// reset isRTCAlarmWake. This evaluation should happen only once
8420 			// on RTC/Alarm wake. Any clamshell events after wake should follow
8421 			// the regular evaluation
8422 			isRTCAlarmWake = false;
8423 		} else {
8424 			eval_clamshell = true;
8425 		}
8426 	}
8427 
8428 	/*
8429 	 * Overtemp
8430 	 */
8431 	if (msg & kIOPMOverTemp) {
8432 		DLOG("Thermal overtemp message received!\n");
8433 		thermalEmergencyState = true;
8434 		privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8435 	}
8436 
8437 	/*
8438 	 * Forward DW thermal notification to client, if system is not going to sleep
8439 	 */
8440 	if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8441 		DLOG("DarkWake thermal limits message received!\n");
8442 		messageClients(kIOPMMessageDarkWakeThermalEmergency);
8443 	}
8444 
8445 	/*
8446 	 * Sleep Now!
8447 	 */
8448 	if (msg & kIOPMSleepNow) {
8449 		privateSleepSystem(kIOPMSleepReasonSoftware);
8450 	}
8451 
8452 	/*
8453 	 * Power Emergency
8454 	 */
8455 	if (msg & kIOPMPowerEmergency) {
8456 		DLOG("Received kIOPMPowerEmergency");
8457 #if HIBERNATION && defined(__arm64__)
8458 		if (!ml_is_secure_hib_supported()) {
8459 			// Wait for the next low battery notification if the system state is
8460 			// in transition.
8461 			if ((_systemTransitionType == kSystemTransitionNone) &&
8462 			    CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8463 			    !systemBooting && !systemShutdown && !gWillShutdown) {
8464 				// Setting lowBatteryCondition will prevent system sleep
8465 				lowBatteryCondition = true;
8466 
8467 				// Notify userspace to initiate system shutdown
8468 				messageClients(kIOPMMessageRequestSystemShutdown);
8469 			}
8470 		} else {
8471 			lowBatteryCondition = true;
8472 			privateSleepSystem(kIOPMSleepReasonLowPower);
8473 		}
8474 #else  /* HIBERNATION && defined(__arm64__) */
8475 		lowBatteryCondition = true;
8476 		privateSleepSystem(kIOPMSleepReasonLowPower);
8477 #endif /* HIBERNATION && defined(__arm64__) */
8478 	}
8479 
8480 	/*
8481 	 * Clamshell OPEN
8482 	 */
8483 	if (msg & kIOPMClamshellOpened) {
8484 		DLOG("Clamshell opened\n");
8485 		// Received clamshel open message from clamshell controlling driver
8486 		// Update our internal state and tell general interest clients
8487 		clamshellClosed = false;
8488 		clamshellExists = true;
8489 
8490 		// Don't issue a hid tickle when lid is open and polled on wake
8491 		if (msg & kIOPMSetValue) {
8492 			setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8493 			reportUserInput();
8494 		}
8495 
8496 		// Tell PMCPU
8497 		informCPUStateChange(kInformLid, 0);
8498 
8499 		// Tell general interest clients
8500 		sendClientClamshellNotification();
8501 
8502 		bool aborting =  ((lastSleepReason == kIOPMSleepReasonClamshell)
8503 		    || (lastSleepReason == kIOPMSleepReasonIdle)
8504 		    || (lastSleepReason == kIOPMSleepReasonMaintenance));
8505 		if (aborting) {
8506 			userActivityCount++;
8507 		}
8508 		DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8509 	}
8510 
8511 	/*
8512 	 * Clamshell CLOSED
8513 	 * Send the clamshell interest notification since the lid is closing.
8514 	 */
8515 	if (msg & kIOPMClamshellClosed) {
8516 		if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8517 		    clamshellClosed && clamshellExists) {
8518 			DLOG("Ignoring redundant Clamshell close event\n");
8519 		} else {
8520 			DLOG("Clamshell closed\n");
8521 			// Received clamshel open message from clamshell controlling driver
8522 			// Update our internal state and tell general interest clients
8523 			clamshellClosed = true;
8524 			clamshellExists = true;
8525 
8526 			// Ignore all following clamshell close events until the clamshell
8527 			// is opened or the system sleeps. When a clamshell close triggers
8528 			// a system wake, the lid driver may send us two clamshell close
8529 			// events, one for the clamshell close event itself, and a second
8530 			// close event when the driver polls the lid state on wake.
8531 			clamshellIgnoreClose = true;
8532 
8533 			// Tell PMCPU
8534 			informCPUStateChange(kInformLid, 1);
8535 
8536 			// Tell general interest clients
8537 			sendClientClamshellNotification();
8538 
8539 			// And set eval_clamshell = so we can attempt
8540 			eval_clamshell = true;
8541 		}
8542 	}
8543 
8544 	/*
8545 	 * Set Desktop mode (sent from graphics)
8546 	 *
8547 	 *  -> reevaluate lid state
8548 	 */
8549 	if (msg & kIOPMSetDesktopMode) {
8550 		desktopMode = (0 != (msg & kIOPMSetValue));
8551 		msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8552 		DLOG("Desktop mode %d\n", desktopMode);
8553 
8554 		sendClientClamshellNotification();
8555 
8556 		// Re-evaluate the lid state
8557 		eval_clamshell = true;
8558 	}
8559 
8560 	/*
8561 	 * AC Adaptor connected
8562 	 *
8563 	 *  -> reevaluate lid state
8564 	 */
8565 	if (msg & kIOPMSetACAdaptorConnected) {
8566 		acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8567 		msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8568 
8569 		// Tell CPU PM
8570 		informCPUStateChange(kInformAC, !acAdaptorConnected);
8571 
8572 		// Tell BSD if AC is connected
8573 		//      0 == external power source; 1 == on battery
8574 		post_sys_powersource(acAdaptorConnected ? 0:1);
8575 
8576 		sendClientClamshellNotification();
8577 
8578 		IOUserServer::powerSourceChanged(acAdaptorConnected);
8579 
8580 		// Re-evaluate the lid state
8581 		eval_clamshell = true;
8582 
8583 		// Lack of AC may have latched a display wrangler tickle.
8584 		// This mirrors the hardware's USB wake event latch, where a latched
8585 		// USB wake event followed by an AC attach will trigger a full wake.
8586 		latchDisplayWranglerTickle( false );
8587 
8588 #if HIBERNATION
8589 		// AC presence will reset the standy timer delay adjustment.
8590 		_standbyTimerResetSeconds = 0;
8591 #endif
8592 		if (!userIsActive) {
8593 			// Reset userActivityTime when power supply is changed(rdr 13789330)
8594 			clock_get_uptime(&userActivityTime);
8595 		}
8596 	}
8597 
8598 	/*
8599 	 * Enable Clamshell (external display disappear)
8600 	 *
8601 	 *  -> reevaluate lid state
8602 	 */
8603 	if (msg & kIOPMEnableClamshell) {
8604 		DLOG("Clamshell enabled\n");
8605 
8606 		// Re-evaluate the lid state
8607 		// System should sleep on external display disappearance
8608 		// in lid closed operation.
8609 		if (true == clamshellDisabled) {
8610 			eval_clamshell = true;
8611 
8612 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8613 			// Also clear kClamshellSleepDisableInternal when graphics enables
8614 			// the clamshell during a full wake. When graphics is behaving as
8615 			// expected, this will allow clamshell close to be honored earlier
8616 			// rather than waiting for the delayed evaluation.
8617 			if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8618 			    (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8619 			    CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8620 				setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8621 
8622 				// Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8623 				// when timer expires which is harmless but useless.
8624 				thread_call_cancel(fullWakeThreadCall);
8625 			}
8626 #endif
8627 		}
8628 
8629 		clamshellDisabled = false;
8630 		sendClientClamshellNotification();
8631 	}
8632 
8633 	/*
8634 	 * Disable Clamshell (external display appeared)
8635 	 * We don't bother re-evaluating clamshell state. If the system is awake,
8636 	 * the lid is probably open.
8637 	 */
8638 	if (msg & kIOPMDisableClamshell) {
8639 		DLOG("Clamshell disabled\n");
8640 		clamshellDisabled = true;
8641 		sendClientClamshellNotification();
8642 	}
8643 
8644 	/*
8645 	 * Evaluate clamshell and SLEEP if appropriate
8646 	 */
8647 	if (eval_clamshell_alarm && clamshellClosed) {
8648 		if (shouldSleepOnRTCAlarmWake()) {
8649 			privateSleepSystem(kIOPMSleepReasonClamshell);
8650 		}
8651 	} else if (eval_clamshell && clamshellClosed) {
8652 		if (shouldSleepOnClamshellClosed()) {
8653 			privateSleepSystem(kIOPMSleepReasonClamshell);
8654 		} else {
8655 			evaluatePolicy( kStimulusDarkWakeEvaluate );
8656 		}
8657 	}
8658 
8659 	if (msg & kIOPMProModeEngaged) {
8660 		int newState = 1;
8661 		DLOG("ProModeEngaged\n");
8662 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8663 	}
8664 
8665 	if (msg & kIOPMProModeDisengaged) {
8666 		int newState = 0;
8667 		DLOG("ProModeDisengaged\n");
8668 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8669 	}
8670 }
8671 
8672 //******************************************************************************
8673 // evaluatePolicy
8674 //
8675 // Evaluate root-domain policy in response to external changes.
8676 //******************************************************************************
8677 
8678 void
8679 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8680 {
8681 	union {
8682 		struct {
8683 			int idleSleepEnabled    : 1;
8684 			int idleSleepDisabled   : 1;
8685 			int displaySleep        : 1;
8686 			int sleepDelayChanged   : 1;
8687 			int evaluateDarkWake    : 1;
8688 			int adjustPowerState    : 1;
8689 			int userBecameInactive  : 1;
8690 			int displaySleepEntry   : 1;
8691 		} bit;
8692 		uint32_t u32;
8693 	} flags;
8694 
8695 
8696 	ASSERT_GATED();
8697 	flags.u32 = 0;
8698 
8699 	switch (stimulus) {
8700 	case kStimulusDisplayWranglerSleep:
8701 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8702 		if (!wranglerPowerOff) {
8703 			// wrangler is in sleep state or lower
8704 			flags.bit.displaySleep = true;
8705 		}
8706 		if (!wranglerAsleep) {
8707 			// transition from wrangler wake to wrangler sleep
8708 			flags.bit.displaySleepEntry = true;
8709 			wranglerAsleep = true;
8710 		}
8711 		break;
8712 
8713 	case kStimulusDisplayWranglerWake:
8714 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8715 		displayIdleForDemandSleep = false;
8716 		wranglerPowerOff = false;
8717 		wranglerAsleep = false;
8718 		break;
8719 
8720 	case kStimulusEnterUserActiveState:
8721 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8722 		if (_preventUserActive) {
8723 			DLOG("user active dropped\n");
8724 			break;
8725 		}
8726 		if (!userIsActive) {
8727 			userIsActive = true;
8728 			userWasActive = true;
8729 			clock_get_uptime(&gUserActiveAbsTime);
8730 
8731 			// Stay awake after dropping demand for display power on
8732 			if (kFullWakeReasonDisplayOn == fullWakeReason) {
8733 				fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8734 				DLOG("User activity while in notification wake\n");
8735 				changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8736 			}
8737 
8738 			kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8739 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8740 			messageClients(kIOPMMessageUserIsActiveChanged);
8741 		}
8742 		flags.bit.idleSleepDisabled = true;
8743 		break;
8744 
8745 	case kStimulusLeaveUserActiveState:
8746 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8747 		if (userIsActive) {
8748 			clock_get_uptime(&gUserInactiveAbsTime);
8749 			userIsActive = false;
8750 			clock_get_uptime(&userBecameInactiveTime);
8751 			flags.bit.userBecameInactive = true;
8752 
8753 			kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8754 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8755 			messageClients(kIOPMMessageUserIsActiveChanged);
8756 		}
8757 		break;
8758 
8759 	case kStimulusAggressivenessChanged:
8760 	{
8761 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8762 		unsigned long   aggressiveValue;
8763 		uint32_t        minutesToIdleSleep  = 0;
8764 		uint32_t        minutesToDisplayDim = 0;
8765 		uint32_t        minutesDelta        = 0;
8766 
8767 		// Fetch latest display and system sleep slider values.
8768 		aggressiveValue = 0;
8769 		getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8770 		minutesToIdleSleep = (uint32_t) aggressiveValue;
8771 
8772 		aggressiveValue = 0;
8773 		getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8774 		minutesToDisplayDim = (uint32_t) aggressiveValue;
8775 		DLOG("aggressiveness changed: system %u->%u, display %u\n",
8776 		    sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8777 
8778 		DLOG("idle time -> %d ms (ena %d)\n",
8779 		    idleMilliSeconds, (minutesToIdleSleep != 0));
8780 
8781 		// How long to wait before sleeping the system once
8782 		// the displays turns off is indicated by 'extraSleepDelay'.
8783 
8784 		if (minutesToIdleSleep > minutesToDisplayDim) {
8785 			minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8786 		} else if (minutesToIdleSleep == minutesToDisplayDim) {
8787 			minutesDelta = 1;
8788 		}
8789 
8790 		if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8791 			idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8792 		}
8793 
8794 		if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8795 			flags.bit.idleSleepDisabled = true;
8796 			idleSleepEnabled = false;
8797 		}
8798 #if !defined(XNU_TARGET_OS_OSX)
8799 		if (0x7fffffff == minutesToIdleSleep) {
8800 			minutesToIdleSleep = idleMilliSeconds / 1000;
8801 		}
8802 #endif /* !defined(XNU_TARGET_OS_OSX) */
8803 
8804 		if (((minutesDelta != extraSleepDelay) ||
8805 		    (userActivityTime != userActivityTime_prev)) &&
8806 		    !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8807 			flags.bit.sleepDelayChanged = true;
8808 		}
8809 
8810 		if (systemDarkWake && !darkWakeToSleepASAP &&
8811 		    (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8812 			// Reconsider decision to remain in dark wake
8813 			flags.bit.evaluateDarkWake = true;
8814 		}
8815 
8816 		sleepSlider = minutesToIdleSleep;
8817 		extraSleepDelay = minutesDelta;
8818 		userActivityTime_prev = userActivityTime;
8819 	}   break;
8820 
8821 	case kStimulusDemandSystemSleep:
8822 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8823 		displayIdleForDemandSleep = true;
8824 		if (wrangler && wranglerIdleSettings) {
8825 			// Request wrangler idle only when demand sleep is triggered
8826 			// from full wake.
8827 			if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8828 				wrangler->setProperties(wranglerIdleSettings.get());
8829 				DLOG("Requested wrangler idle\n");
8830 			}
8831 		}
8832 		// arg = sleepReason
8833 		changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8834 		break;
8835 
8836 	case kStimulusAllowSystemSleepChanged:
8837 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8838 		flags.bit.adjustPowerState = true;
8839 		break;
8840 
8841 	case kStimulusDarkWakeActivityTickle:
8842 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8843 		// arg == true implies real and not self generated wrangler tickle.
8844 		// Update wake type on PM work loop instead of the tickle thread to
8845 		// eliminate the possibility of an early tickle clobbering the wake
8846 		// type set by the platform driver.
8847 		if (arg == true) {
8848 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8849 		}
8850 
8851 		if (!darkWakeExit) {
8852 			if (latchDisplayWranglerTickle(true)) {
8853 				DLOG("latched tickle\n");
8854 				break;
8855 			}
8856 
8857 			darkWakeExit = true;
8858 			DLOG("Requesting full wake due to dark wake activity tickle\n");
8859 			requestFullWake( kFullWakeReasonLocalUser );
8860 		}
8861 		break;
8862 
8863 	case kStimulusDarkWakeEntry:
8864 	case kStimulusDarkWakeReentry:
8865 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8866 		// Any system transitions since the last dark wake transition
8867 		// will invalid the stimulus.
8868 
8869 		if (arg == _systemStateGeneration) {
8870 			DLOG("dark wake entry\n");
8871 			systemDarkWake = true;
8872 
8873 			// Keep wranglerPowerOff an invariant when wrangler is absent
8874 			if (wrangler) {
8875 				wranglerPowerOff = true;
8876 			}
8877 
8878 			if (kStimulusDarkWakeEntry == stimulus) {
8879 				clock_get_uptime(&userBecameInactiveTime);
8880 				flags.bit.evaluateDarkWake = true;
8881 				if (activitySinceSleep()) {
8882 					DLOG("User activity recorded while going to darkwake\n");
8883 					reportUserInput();
8884 				}
8885 			}
8886 
8887 			// Always accelerate disk spindown while in dark wake,
8888 			// even if system does not support/allow sleep.
8889 
8890 			cancelIdleSleepTimer();
8891 			setQuickSpinDownTimeout();
8892 		}
8893 		break;
8894 
8895 	case kStimulusDarkWakeEvaluate:
8896 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8897 		if (systemDarkWake) {
8898 			flags.bit.evaluateDarkWake = true;
8899 		}
8900 		break;
8901 
8902 	case kStimulusNoIdleSleepPreventers:
8903 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8904 		flags.bit.adjustPowerState = true;
8905 		break;
8906 	} /* switch(stimulus) */
8907 
8908 	if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8909 		DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8910 		    darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8911 		if (darkWakeToSleepASAP ||
8912 		    (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8913 			uint32_t newSleepReason;
8914 
8915 			if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8916 				// System was previously in full wake. Sleep reason from
8917 				// full to dark already recorded in fullToDarkReason.
8918 
8919 				if (lowBatteryCondition) {
8920 					newSleepReason = kIOPMSleepReasonLowPower;
8921 				} else if (thermalEmergencyState) {
8922 					newSleepReason = kIOPMSleepReasonThermalEmergency;
8923 				} else {
8924 					newSleepReason = fullToDarkReason;
8925 				}
8926 			} else {
8927 				// In dark wake from system sleep.
8928 
8929 				if (darkWakeSleepService) {
8930 					newSleepReason = kIOPMSleepReasonSleepServiceExit;
8931 				} else {
8932 					newSleepReason = kIOPMSleepReasonMaintenance;
8933 				}
8934 			}
8935 
8936 			if (checkSystemCanSleep(newSleepReason)) {
8937 				privateSleepSystem(newSleepReason);
8938 			}
8939 		} else { // non-maintenance (network) dark wake
8940 			if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8941 				// Release power clamp, and wait for children idle.
8942 				adjustPowerState(true);
8943 			} else {
8944 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8945 			}
8946 		}
8947 	}
8948 
8949 	if (systemDarkWake) {
8950 		// The rest are irrelevant while system is in dark wake.
8951 		flags.u32 = 0;
8952 	}
8953 
8954 	if ((flags.bit.displaySleepEntry) &&
8955 	    (kFullWakeReasonDisplayOn == fullWakeReason)) {
8956 		// kIOPMSleepReasonNotificationWakeExit
8957 		DLOG("Display sleep while in notification wake\n");
8958 		changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8959 	}
8960 
8961 	if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8962 		bool cancelQuickSpindown = false;
8963 
8964 		if (flags.bit.sleepDelayChanged) {
8965 			// Cancel existing idle sleep timer and quick disk spindown.
8966 			// New settings will be applied by the idleSleepEnabled flag
8967 			// handler below if idle sleep is enabled.
8968 
8969 			DLOG("extra sleep timer changed\n");
8970 			cancelIdleSleepTimer();
8971 			cancelQuickSpindown = true;
8972 		} else {
8973 			DLOG("user inactive\n");
8974 		}
8975 
8976 		if (!userIsActive && idleSleepEnabled) {
8977 			startIdleSleepTimer(getTimeToIdleSleep());
8978 		}
8979 
8980 		if (cancelQuickSpindown) {
8981 			restoreUserSpinDownTimeout();
8982 		}
8983 	}
8984 
8985 	if (flags.bit.idleSleepEnabled) {
8986 		DLOG("idle sleep timer enabled\n");
8987 		if (!wrangler) {
8988 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8989 			startIdleSleepTimer(getTimeToIdleSleep());
8990 #else
8991 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8992 			startIdleSleepTimer( idleMilliSeconds );
8993 #endif
8994 		} else {
8995 			// Start idle timer if prefs now allow system sleep
8996 			// and user is already inactive. Disk spindown is
8997 			// accelerated upon timer expiration.
8998 
8999 			if (!userIsActive) {
9000 				startIdleSleepTimer(getTimeToIdleSleep());
9001 			}
9002 		}
9003 	}
9004 
9005 	if (flags.bit.idleSleepDisabled) {
9006 		DLOG("idle sleep timer disabled\n");
9007 		cancelIdleSleepTimer();
9008 		restoreUserSpinDownTimeout();
9009 		adjustPowerState();
9010 	}
9011 
9012 	if (flags.bit.adjustPowerState) {
9013 		bool sleepASAP = false;
9014 
9015 		if (!systemBooting && (0 == idleSleepPreventersCount())) {
9016 			if (!wrangler) {
9017 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9018 				if (idleSleepEnabled) {
9019 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9020 					if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9021 						sleepASAP = true;
9022 					}
9023 #else
9024 					// stay awake for at least idleMilliSeconds
9025 					startIdleSleepTimer(idleMilliSeconds);
9026 #endif
9027 				}
9028 			} else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9029 				sleepASAP = true;
9030 			}
9031 		}
9032 
9033 		adjustPowerState(sleepASAP);
9034 	}
9035 }
9036 
9037 //******************************************************************************
9038 
9039 unsigned int
9040 IOPMrootDomain::idleSleepPreventersCount()
9041 {
9042 	if (_aotMode) {
9043 		unsigned int count __block;
9044 		count = 0;
9045 		preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9046 		{
9047 			count += (NULL == obj->metaCast("AppleARMBacklight"));
9048 			return false;
9049 		});
9050 		return count;
9051 	}
9052 
9053 	return preventIdleSleepList->getCount();
9054 }
9055 
9056 
9057 //******************************************************************************
9058 // requestFullWake
9059 //
9060 // Request transition from dark wake to full wake
9061 //******************************************************************************
9062 
9063 void
9064 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9065 {
9066 	uint32_t        options = 0;
9067 	IOService *     pciRoot = NULL;
9068 	bool            promotion = false;
9069 
9070 	// System must be in dark wake and a valid reason for entering full wake
9071 	if ((kFullWakeReasonNone == reason) ||
9072 	    (kFullWakeReasonNone != fullWakeReason) ||
9073 	    (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9074 		return;
9075 	}
9076 
9077 	// Will clear reason upon exit from full wake
9078 	fullWakeReason = reason;
9079 
9080 	_desiredCapability |= (kIOPMSystemCapabilityGraphics |
9081 	    kIOPMSystemCapabilityAudio);
9082 
9083 	if ((kSystemTransitionWake == _systemTransitionType) &&
9084 	    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9085 	    !darkWakePowerClamped) {
9086 		// Promote to full wake while waking up to dark wake due to tickle.
9087 		// PM will hold off notifying the graphics subsystem about system wake
9088 		// as late as possible, so if a HID tickle does arrive, graphics can
9089 		// power up from this same wake transition. Otherwise, the latency to
9090 		// power up graphics on the following transition can be huge on certain
9091 		// systems. However, once any power clamping has taken effect, it is
9092 		// too late to promote the current dark wake transition to a full wake.
9093 		_pendingCapability |= (kIOPMSystemCapabilityGraphics |
9094 		    kIOPMSystemCapabilityAudio);
9095 
9096 		// Tell the PCI parent of audio and graphics drivers to stop
9097 		// delaying the child notifications. Same for root domain.
9098 		pciRoot = pciHostBridgeDriver.get();
9099 		willEnterFullWake();
9100 		promotion = true;
9101 	}
9102 
9103 	// Unsafe to cancel once graphics was powered.
9104 	// If system woke from dark wake, the return to sleep can
9105 	// be cancelled. "awake -> dark -> sleep" transition
9106 	// can be cancelled also, during the "dark -> sleep" phase
9107 	// *prior* to driver power down.
9108 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9109 	    _pendingCapability == 0) {
9110 		options |= kIOPMSyncCancelPowerDown;
9111 	}
9112 
9113 	synchronizePowerTree(options, pciRoot);
9114 
9115 	if (kFullWakeReasonLocalUser == fullWakeReason) {
9116 		// IOGraphics doesn't light the display even though graphics is
9117 		// enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9118 		// So, do an explicit activity tickle
9119 		if (wrangler) {
9120 			wrangler->activityTickle(0, 0);
9121 		}
9122 	}
9123 
9124 	// Log a timestamp for the initial full wake request.
9125 	// System may not always honor this full wake request.
9126 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9127 		AbsoluteTime    now;
9128 		uint64_t        nsec;
9129 
9130 		clock_get_uptime(&now);
9131 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9132 		absolutetime_to_nanoseconds(now, &nsec);
9133 		MSG("full wake %s (reason %u) %u ms\n",
9134 		    promotion ? "promotion" : "request",
9135 		    fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9136 	}
9137 }
9138 
9139 //******************************************************************************
9140 // willEnterFullWake
9141 //
9142 // System will enter full wake from sleep, from dark wake, or from dark
9143 // wake promotion. This function aggregate things that are in common to
9144 // all three full wake transitions.
9145 //
9146 // Assumptions: fullWakeReason was updated
9147 //******************************************************************************
9148 
9149 void
9150 IOPMrootDomain::willEnterFullWake( void )
9151 {
9152 	hibernateRetry = false;
9153 	sleepToStandby = false;
9154 	standbyNixed   = false;
9155 	resetTimers    = false;
9156 	sleepTimerMaintenance = false;
9157 
9158 	assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9159 
9160 	_systemMessageClientMask = kSystemMessageClientPowerd |
9161 	    kSystemMessageClientLegacyApp;
9162 
9163 	if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9164 		// First time to attain full wake capability since the last wake
9165 		_systemMessageClientMask |= kSystemMessageClientKernel;
9166 
9167 		// Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9168 		setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9169 		    (kFullWakeReasonLocalUser == fullWakeReason) ?
9170 		    kOSBooleanTrue : kOSBooleanFalse);
9171 	}
9172 #if HIBERNATION
9173 	IOHibernateSetWakeCapabilities(_pendingCapability);
9174 #endif
9175 
9176 	IOService::setAdvisoryTickleEnable( true );
9177 	tellClients(kIOMessageSystemWillPowerOn);
9178 	preventTransitionToUserActive(false);
9179 }
9180 
9181 //******************************************************************************
9182 // fullWakeDelayedWork
9183 //
9184 // System has already entered full wake. Invoked by a delayed thread call.
9185 //******************************************************************************
9186 
9187 void
9188 IOPMrootDomain::fullWakeDelayedWork( void )
9189 {
9190 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9191 	if (!gIOPMWorkLoop->inGate()) {
9192 		gIOPMWorkLoop->runAction(
9193 			OSMemberFunctionCast(IOWorkLoop::Action, this,
9194 			&IOPMrootDomain::fullWakeDelayedWork), this);
9195 		return;
9196 	}
9197 
9198 	DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9199 	    _currentCapability, _pendingCapability, _highestCapability,
9200 	    clamshellDisabled, clamshellSleepDisableMask);
9201 
9202 	if (clamshellExists &&
9203 	    CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9204 	    !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9205 		if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9206 			setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9207 		} else {
9208 			// Not the initial full wake after waking from sleep.
9209 			// Evaluate the clamshell for rdar://problem/9157444.
9210 			receivePowerNotification(kLocalEvalClamshellCommand);
9211 		}
9212 	}
9213 #endif
9214 }
9215 
9216 //******************************************************************************
9217 // evaluateAssertions
9218 //
9219 //******************************************************************************
9220 
9221 // Bitmask of all kernel assertions that prevent system idle sleep.
9222 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9223 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9224 	(kIOPMDriverAssertionReservedBit7 | \
9225 	 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9226 
9227 void
9228 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9229 {
9230 	IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9231 
9232 	messageClients(kIOPMMessageDriverAssertionsChanged);
9233 
9234 	if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9235 		if (wrangler) {
9236 			bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9237 
9238 			DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9239 			wrangler->setIgnoreIdleTimer( value );
9240 		}
9241 	}
9242 
9243 	if (changedBits & kIOPMDriverAssertionCPUBit) {
9244 		if (_aotNow) {
9245 			IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9246 		}
9247 		evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9248 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9249 			AbsoluteTime    now;
9250 			clock_usec_t    microsecs;
9251 			clock_get_uptime(&now);
9252 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9253 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
9254 			if (assertOnWakeReport) {
9255 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9256 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9257 			}
9258 		}
9259 	}
9260 
9261 	if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9262 		if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9263 			if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9264 				DLOG("PreventIdleSleep driver assertion raised\n");
9265 				bool ok = updatePreventIdleSleepList(this, true);
9266 				if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9267 					// Cancel idle sleep if there is one in progress
9268 					cancelIdlePowerDown(this);
9269 				}
9270 			}
9271 		} else {
9272 			DLOG("PreventIdleSleep driver assertion dropped\n");
9273 			updatePreventIdleSleepList(this, false);
9274 		}
9275 	}
9276 }
9277 
9278 // MARK: -
9279 // MARK: Statistics
9280 
9281 //******************************************************************************
9282 // pmStats
9283 //
9284 //******************************************************************************
9285 
9286 void
9287 IOPMrootDomain::pmStatsRecordEvent(
9288 	int                 eventIndex,
9289 	AbsoluteTime        timestamp)
9290 {
9291 	bool        starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9292 	bool        stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9293 	uint64_t    delta;
9294 	uint64_t    nsec;
9295 	OSSharedPtr<OSData> publishPMStats;
9296 
9297 	eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9298 
9299 	absolutetime_to_nanoseconds(timestamp, &nsec);
9300 
9301 	switch (eventIndex) {
9302 	case kIOPMStatsHibernateImageWrite:
9303 		if (starting) {
9304 			gPMStats.hibWrite.start = nsec;
9305 		} else if (stopping) {
9306 			gPMStats.hibWrite.stop = nsec;
9307 		}
9308 
9309 		if (stopping) {
9310 			delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9311 			IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9312 		}
9313 		break;
9314 	case kIOPMStatsHibernateImageRead:
9315 		if (starting) {
9316 			gPMStats.hibRead.start = nsec;
9317 		} else if (stopping) {
9318 			gPMStats.hibRead.stop = nsec;
9319 		}
9320 
9321 		if (stopping) {
9322 			delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9323 			IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9324 
9325 			publishPMStats = OSData::withValue(gPMStats);
9326 			setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9327 			bzero(&gPMStats, sizeof(gPMStats));
9328 		}
9329 		break;
9330 	}
9331 }
9332 
9333 /*
9334  * Appends a record of the application response to
9335  * IOPMrootDomain::pmStatsAppResponses
9336  */
9337 void
9338 IOPMrootDomain::pmStatsRecordApplicationResponse(
9339 	const OSSymbol      *response,
9340 	const char          *name,
9341 	int                 messageType,
9342 	uint32_t            delay_ms,
9343 	uint64_t            id,
9344 	OSObject            *object,
9345 	IOPMPowerStateIndex powerState,
9346 	bool                async)
9347 {
9348 	OSSharedPtr<OSDictionary>    responseDescription;
9349 	OSSharedPtr<OSNumber>        delayNum;
9350 	OSSharedPtr<OSNumber>        powerCaps;
9351 	OSSharedPtr<OSNumber>        pidNum;
9352 	OSSharedPtr<OSNumber>        msgNum;
9353 	OSSharedPtr<const OSSymbol>  appname;
9354 	OSSharedPtr<const OSSymbol>  sleep;
9355 	OSSharedPtr<const OSSymbol>  wake;
9356 	IOPMServiceInterestNotifier *notify = NULL;
9357 
9358 	if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9359 		if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9360 			notify->ackTimeoutCnt++;
9361 		} else {
9362 			notify->ackTimeoutCnt = 0;
9363 		}
9364 	}
9365 
9366 	if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9367 	    (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9368 		return;
9369 	}
9370 
9371 
9372 	if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9373 		kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9374 	} else if (notify) {
9375 		// User space app or kernel capability client
9376 		if (id) {
9377 			kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9378 		} else {
9379 			kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9380 		}
9381 		notify->msgType = 0;
9382 	}
9383 
9384 	responseDescription = OSDictionary::withCapacity(5);
9385 	if (responseDescription) {
9386 		if (response) {
9387 			responseDescription->setObject(_statsResponseTypeKey.get(), response);
9388 		}
9389 
9390 		msgNum = OSNumber::withNumber(messageType, 32);
9391 		if (msgNum) {
9392 			responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9393 		}
9394 
9395 		if (!name && notify && notify->identifier) {
9396 			name = notify->identifier->getCStringNoCopy();
9397 		}
9398 
9399 		if (name && (strlen(name) > 0)) {
9400 			appname = OSSymbol::withCString(name);
9401 			if (appname) {
9402 				responseDescription->setObject(_statsNameKey.get(), appname.get());
9403 			}
9404 		}
9405 
9406 		if (!id && notify) {
9407 			id = notify->uuid0;
9408 		}
9409 		pidNum = OSNumber::withNumber(id, 64);
9410 		if (pidNum) {
9411 			responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9412 		}
9413 
9414 		delayNum = OSNumber::withNumber(delay_ms, 32);
9415 		if (delayNum) {
9416 			responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9417 		}
9418 
9419 		if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9420 			powerCaps = OSNumber::withNumber(powerState, 32);
9421 
9422 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9423 			static const char * driverCallTypes[] = {
9424 				[kDriverCallInformPreChange]  = "powerStateWillChangeTo",
9425 				[kDriverCallInformPostChange] = "powerStateDidChangeTo",
9426 				[kDriverCallSetPowerState]    = "setPowerState"
9427 			};
9428 
9429 			if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9430 				DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9431 				    name, id, driverCallTypes[messageType], (uint32_t) powerState,
9432 				    async ? "async " : "", delay_ms);
9433 			}
9434 #endif
9435 		} else {
9436 			powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9437 		}
9438 		if (powerCaps) {
9439 			responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9440 		}
9441 
9442 		sleep = OSSymbol::withCString("Sleep");
9443 		wake = OSSymbol::withCString("Wake");
9444 		if (_systemTransitionType == kSystemTransitionSleep) {
9445 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9446 		} else if (_systemTransitionType == kSystemTransitionWake) {
9447 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9448 		} else if (_systemTransitionType == kSystemTransitionCapability) {
9449 			if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9450 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9451 			} else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9452 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9453 			}
9454 		}
9455 
9456 		IOLockLock(pmStatsLock);
9457 		if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9458 			pmStatsAppResponses->setObject(responseDescription.get());
9459 		}
9460 		IOLockUnlock(pmStatsLock);
9461 	}
9462 
9463 	return;
9464 }
9465 
9466 // MARK: -
9467 // MARK: PMTraceWorker
9468 
9469 //******************************************************************************
9470 // TracePoint support
9471 //
9472 //******************************************************************************
9473 
9474 #define kIOPMRegisterNVRAMTracePointHandlerKey  \
9475 	"IOPMRegisterNVRAMTracePointHandler"
9476 
9477 IOReturn
9478 IOPMrootDomain::callPlatformFunction(
9479 	const OSSymbol * functionName,
9480 	bool waitForFunction,
9481 	void * param1, void * param2,
9482 	void * param3, void * param4 )
9483 {
9484 	if (pmTracer && functionName &&
9485 	    functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9486 	    !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9487 		uint32_t    tracePointPhases, tracePointPCI;
9488 		uint64_t    statusCode;
9489 
9490 		pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9491 		pmTracer->tracePointTarget  = (void *) param2;
9492 		tracePointPCI               = (uint32_t)(uintptr_t) param3;
9493 		tracePointPhases            = (uint32_t)(uintptr_t) param4;
9494 		if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9495 			OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9496 			if (node) {
9497 				OSSharedPtr<OSObject> bootRomFailureProp;
9498 				bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9499 				OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9500 				uint32_t bootFailureCode;
9501 				if (data && data->getLength() == sizeof(bootFailureCode)) {
9502 					// Failure code from EFI/BootRom is a four byte structure
9503 					memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9504 					tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9505 				}
9506 			}
9507 		}
9508 		statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9509 		if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9510 			MSG("Sleep failure code 0x%08x 0x%08x\n",
9511 			    tracePointPCI, tracePointPhases);
9512 		}
9513 		setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9514 		pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9515 
9516 		return kIOReturnSuccess;
9517 	}
9518 #if HIBERNATION
9519 	else if (functionName &&
9520 	    functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9521 		if (gSleepPolicyHandler) {
9522 			return kIOReturnExclusiveAccess;
9523 		}
9524 		if (!param1) {
9525 			return kIOReturnBadArgument;
9526 		}
9527 		gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9528 		gSleepPolicyTarget  = (void *) param2;
9529 		setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9530 		return kIOReturnSuccess;
9531 	}
9532 #endif
9533 
9534 	return super::callPlatformFunction(
9535 		functionName, waitForFunction, param1, param2, param3, param4);
9536 }
9537 
9538 void
9539 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9540     uintptr_t param1, uintptr_t param2, uintptr_t param3)
9541 {
9542 	uint32_t code   = IODBG_POWER(event);
9543 	uint64_t regId  = id;
9544 	if (regId == 0) {
9545 		regId  = getRegistryEntryID();
9546 	}
9547 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9548 }
9549 
9550 void
9551 IOPMrootDomain::tracePoint( uint8_t point )
9552 {
9553 	if (systemBooting) {
9554 		return;
9555 	}
9556 
9557 	if (kIOPMTracePointWakeCapabilityClients == point) {
9558 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9559 	}
9560 
9561 	kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9562 	pmTracer->tracePoint(point);
9563 }
9564 
9565 static void
9566 kext_log_putc(char c)
9567 {
9568 	if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9569 		return;
9570 	}
9571 	if (c == '(' || c == '[' || c == ' ') {
9572 		c = 0;
9573 		gKextNameEnd = true;
9574 	}
9575 
9576 	gKextNameBuf[gKextNamePos++] = c;
9577 }
9578 
9579 static int
9580 kext_log(const char *fmt, ...)
9581 {
9582 	va_list listp;
9583 
9584 	va_start(listp, fmt);
9585 	_doprnt(fmt, &listp, &kext_log_putc, 16);
9586 	va_end(listp);
9587 
9588 	return 0;
9589 }
9590 
9591 static OSPtr<const OSSymbol>
9592 copyKextIdentifierWithAddress(vm_address_t address)
9593 {
9594 	OSSharedPtr<const OSSymbol> identifer;
9595 
9596 	IOLockLock(gHaltLogLock);
9597 
9598 	gKextNameEnd = false;
9599 	gKextNamePos = 0;
9600 	gKextNameBuf[0] = 0;
9601 
9602 	OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9603 	gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9604 	identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9605 
9606 	IOLockUnlock(gHaltLogLock);
9607 
9608 	return identifer;
9609 }
9610 
9611 // Caller serialized using PM workloop
9612 const char *
9613 IOPMrootDomain::getNotificationClientName(OSObject *object)
9614 {
9615 	IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9616 	const char *clientName = "UNKNOWN";
9617 
9618 	if (!notifier->clientName) {
9619 		// Check for user client
9620 		if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9621 			OSNumber *clientID = NULL;
9622 			messageClient(kIOMessageCopyClientID, object, &clientID);
9623 			if (clientID) {
9624 				OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9625 				if (string) {
9626 					notifier->clientName = OSSymbol::withString(string.get());
9627 				}
9628 				clientID->release();
9629 			}
9630 		} else if (notifier->identifier) {
9631 			notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9632 		}
9633 	}
9634 
9635 	if (notifier->clientName) {
9636 		clientName = notifier->clientName->getCStringNoCopy();
9637 	}
9638 
9639 	return clientName;
9640 }
9641 
9642 void
9643 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9644 {
9645 	IOPMServiceInterestNotifier *notifier;
9646 
9647 	if (systemBooting) {
9648 		return;
9649 	}
9650 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9651 	if (!notifier) {
9652 		return;
9653 	}
9654 
9655 	if (start) {
9656 		pmTracer->traceDetail(notifier->uuid0 >> 32);
9657 		kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9658 		    (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9659 
9660 		// Update notifier state used for response/ack logging
9661 		notifier->msgIndex = msgIndex;
9662 		notifier->msgAbsTime = timestamp;
9663 
9664 		if (msgIndex != UINT_MAX) {
9665 			DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9666 		} else {
9667 			DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9668 		}
9669 
9670 		assert(notifierObject == NULL);
9671 		notifierThread = current_thread();
9672 		notifierObject.reset(notifier, OSRetain);
9673 	} else {
9674 		uint64_t nsec;
9675 		uint32_t delayMS;
9676 
9677 		SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9678 		absolutetime_to_nanoseconds(timestamp, &nsec);
9679 		delayMS = (uint32_t)(nsec / 1000000ULL);
9680 		if (delayMS > notifier->maxMsgDelayMS) {
9681 			notifier->maxMsgDelayMS = delayMS;
9682 		}
9683 
9684 		assert(notifierObject == notifier);
9685 		notifierObject.reset();
9686 		notifierThread = NULL;
9687 	}
9688 }
9689 
9690 void
9691 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9692 {
9693 	if (systemBooting) {
9694 		return;
9695 	}
9696 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9697 	if (!notifier) {
9698 		return;
9699 	}
9700 
9701 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9702 	    (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9703 
9704 	DLOG("%s[%u] ack from %s took %d ms\n",
9705 	    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9706 	if (delay_ms > notifier->maxAckDelayMS) {
9707 		notifier->maxAckDelayMS = delay_ms;
9708 	}
9709 }
9710 
9711 void
9712 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9713 {
9714 	if (systemBooting) {
9715 		return;
9716 	}
9717 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9718 	if (!notifier) {
9719 		return;
9720 	}
9721 
9722 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9723 	    (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9724 
9725 	if (ack_time_us == 0) {
9726 		// Client work is done and ack will not be forthcoming
9727 		DLOG("%s[%u] response from %s took %d ms\n",
9728 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9729 	} else {
9730 		// Client needs more time and it must ack within ack_time_us
9731 		DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9732 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9733 	}
9734 }
9735 
9736 void
9737 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9738 {
9739 	if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9740 		return;
9741 	}
9742 	if (systemBooting) {
9743 		return;
9744 	}
9745 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9746 	if (!notifier) {
9747 		return;
9748 	}
9749 
9750 	DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9751 }
9752 
9753 void
9754 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9755 {
9756 	if (!systemBooting) {
9757 		uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9758 		pmTracer->traceDetail( detail );
9759 		kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9760 		DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9761 	}
9762 }
9763 
9764 void
9765 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9766 {
9767 	size_t      reportSize;
9768 	void        **report = NULL;
9769 	uint32_t    bktCnt;
9770 	uint32_t    bktSize;
9771 	uint32_t    *clientCnt;
9772 
9773 	ASSERT_GATED();
9774 
9775 	report = NULL;
9776 	if (channel_id == kAssertDelayChID) {
9777 		report = &assertOnWakeReport;
9778 		bktCnt = kAssertDelayBcktCnt;
9779 		bktSize = kAssertDelayBcktSize;
9780 		clientCnt = &assertOnWakeClientCnt;
9781 	} else if (channel_id == kSleepDelaysChID) {
9782 		report = &sleepDelaysReport;
9783 		bktCnt = kSleepDelaysBcktCnt;
9784 		bktSize = kSleepDelaysBcktSize;
9785 		clientCnt = &sleepDelaysClientCnt;
9786 	} else {
9787 		assert(false);
9788 		return;
9789 	}
9790 
9791 	switch (action) {
9792 	case kIOReportEnable:
9793 
9794 		if (*report) {
9795 			(*clientCnt)++;
9796 			break;
9797 		}
9798 
9799 		reportSize = HISTREPORT_BUFSIZE(bktCnt);
9800 		*report = IOMallocZeroData(reportSize);
9801 		if (*report == NULL) {
9802 			break;
9803 		}
9804 		HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9805 		    getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9806 
9807 		if (channel_id == kAssertDelayChID) {
9808 			assertOnWakeSecs = 0;
9809 		}
9810 
9811 		break;
9812 
9813 	case kIOReportDisable:
9814 		if (*clientCnt == 0) {
9815 			break;
9816 		}
9817 		if (*clientCnt == 1) {
9818 			IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9819 			*report = NULL;
9820 		}
9821 		(*clientCnt)--;
9822 
9823 		if (channel_id == kAssertDelayChID) {
9824 			assertOnWakeSecs = -1; // Invalid value to prevent updates
9825 		}
9826 		break;
9827 
9828 	case kIOReportGetDimensions:
9829 		if (*report) {
9830 			HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9831 		}
9832 		break;
9833 	}
9834 
9835 	return;
9836 }
9837 
9838 IOReturn
9839 IOPMrootDomain::configureReport(IOReportChannelList    *channelList,
9840     IOReportConfigureAction action,
9841     void                   *result,
9842     void                   *destination)
9843 {
9844 	unsigned cnt;
9845 	uint64_t configAction = (uint64_t)action;
9846 
9847 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9848 		if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9849 		    (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9850 		    (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9851 			if (action != kIOReportGetDimensions) {
9852 				continue;
9853 			}
9854 			SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9855 		} else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9856 		    (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9857 			gIOPMWorkLoop->runAction(
9858 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9859 				(OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9860 				(void *)configAction, (void *)result);
9861 		}
9862 	}
9863 
9864 	return super::configureReport(channelList, action, result, destination);
9865 }
9866 
9867 IOReturn
9868 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9869 {
9870 	uint32_t    size2cpy;
9871 	void        *data2cpy;
9872 	void        **report;
9873 
9874 	ASSERT_GATED();
9875 
9876 	report = NULL;
9877 	if (ch_id == kAssertDelayChID) {
9878 		report = &assertOnWakeReport;
9879 	} else if (ch_id == kSleepDelaysChID) {
9880 		report = &sleepDelaysReport;
9881 	} else {
9882 		assert(false);
9883 		return kIOReturnBadArgument;
9884 	}
9885 
9886 	if (*report == NULL) {
9887 		return kIOReturnNotOpen;
9888 	}
9889 
9890 	HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9891 	if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9892 		return kIOReturnOverrun;
9893 	}
9894 
9895 	HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9896 	dest->appendBytes(data2cpy, size2cpy);
9897 
9898 	return kIOReturnSuccess;
9899 }
9900 
9901 IOReturn
9902 IOPMrootDomain::updateReport(IOReportChannelList      *channelList,
9903     IOReportUpdateAction      action,
9904     void                     *result,
9905     void                     *destination)
9906 {
9907 	uint32_t size2cpy;
9908 	void *data2cpy;
9909 	uint8_t buf[SIMPLEREPORT_BUFSIZE];
9910 	IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9911 	unsigned cnt;
9912 	uint64_t ch_id;
9913 
9914 	if (action != kIOReportCopyChannelData) {
9915 		goto exit;
9916 	}
9917 
9918 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9919 		ch_id = channelList->channels[cnt].channel_id;
9920 
9921 		if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9922 			gIOPMWorkLoop->runAction(
9923 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9924 				(OSObject *)this, (void *)ch_id,
9925 				(void *)result, (void *)dest);
9926 			continue;
9927 		} else if ((ch_id == kSleepCntChID) ||
9928 		    (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9929 			SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9930 		} else {
9931 			continue;
9932 		}
9933 
9934 		if (ch_id == kSleepCntChID) {
9935 			SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9936 		} else if (ch_id == kDarkWkCntChID) {
9937 			SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9938 		} else if (ch_id == kUserWkCntChID) {
9939 			SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9940 		}
9941 
9942 		SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9943 		SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9944 		dest->appendBytes(data2cpy, size2cpy);
9945 	}
9946 
9947 exit:
9948 	return super::updateReport(channelList, action, result, destination);
9949 }
9950 
9951 
9952 //******************************************************************************
9953 // PMTraceWorker Class
9954 //
9955 //******************************************************************************
9956 
9957 #undef super
9958 #define super OSObject
9959 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9960 
9961 #define kPMBestGuessPCIDevicesCount     25
9962 #define kPMMaxRTCBitfieldSize           32
9963 
9964 OSPtr<PMTraceWorker>
9965 PMTraceWorker::tracer(IOPMrootDomain * owner)
9966 {
9967 	OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9968 	if (!me || !me->init()) {
9969 		return NULL;
9970 	}
9971 
9972 	DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9973 
9974 	// Note that we cannot instantiate the PCI device -> bit mappings here, since
9975 	// the IODeviceTree has not yet been created by IOPlatformExpert. We create
9976 	// this dictionary lazily.
9977 	me->owner = owner;
9978 	me->pciDeviceBitMappings = NULL;
9979 	me->pmTraceWorkerLock = IOLockAlloc();
9980 	me->tracePhase = kIOPMTracePointSystemUp;
9981 	me->traceData32 = 0;
9982 	me->loginWindowData = 0;
9983 	me->coreDisplayData = 0;
9984 	me->coreGraphicsData = 0;
9985 	return me;
9986 }
9987 
9988 void
9989 PMTraceWorker::RTC_TRACE(void)
9990 {
9991 	if (tracePointHandler && tracePointTarget) {
9992 		uint32_t    wordA;
9993 
9994 		IOLockLock(pmTraceWorkerLock);
9995 		wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9996 		    (coreGraphicsData << 8) | tracePhase;
9997 		IOLockUnlock(pmTraceWorkerLock);
9998 
9999 		tracePointHandler( tracePointTarget, traceData32, wordA );
10000 		_LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10001 	}
10002 #if DEVELOPMENT || DEBUG
10003 	if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10004 		DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10005 		IOLock *l = IOLockAlloc();
10006 		IOLockLock(l);
10007 		IOLockLock(l);
10008 	}
10009 #endif /* DEVELOPMENT || DEBUG */
10010 }
10011 
10012 int
10013 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10014 {
10015 	OSSharedPtr<const OSSymbol>    deviceName;
10016 	int                 index = -1;
10017 
10018 	IOLockLock(pmTraceWorkerLock);
10019 
10020 	if (!pciDeviceBitMappings) {
10021 		pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10022 		if (!pciDeviceBitMappings) {
10023 			goto exit;
10024 		}
10025 	}
10026 
10027 	// Check for bitmask overflow.
10028 	if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10029 		goto exit;
10030 	}
10031 
10032 	if ((deviceName = pciDevice->copyName()) &&
10033 	    (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10034 	    pciDeviceBitMappings->setObject(deviceName.get())) {
10035 		index = pciDeviceBitMappings->getCount() - 1;
10036 		_LOG("PMTrace PCI array: set object %s => %d\n",
10037 		    deviceName->getCStringNoCopy(), index);
10038 	}
10039 
10040 	if (!addedToRegistry && (index >= 0)) {
10041 		addedToRegistry = owner->setProperty("PCITopLevel", this);
10042 	}
10043 
10044 exit:
10045 	IOLockUnlock(pmTraceWorkerLock);
10046 	return index;
10047 }
10048 
10049 bool
10050 PMTraceWorker::serialize(OSSerialize *s) const
10051 {
10052 	bool ok = false;
10053 	if (pciDeviceBitMappings) {
10054 		IOLockLock(pmTraceWorkerLock);
10055 		ok = pciDeviceBitMappings->serialize(s);
10056 		IOLockUnlock(pmTraceWorkerLock);
10057 	}
10058 	return ok;
10059 }
10060 
10061 void
10062 PMTraceWorker::tracePoint(uint8_t phase)
10063 {
10064 	// clear trace detail when phase begins
10065 	if (tracePhase != phase) {
10066 		traceData32 = 0;
10067 	}
10068 
10069 	tracePhase = phase;
10070 
10071 	DLOG("trace point 0x%02x\n", tracePhase);
10072 	RTC_TRACE();
10073 }
10074 
10075 void
10076 PMTraceWorker::traceDetail(uint32_t detail)
10077 {
10078 	if (detail == traceData32) {
10079 		return;
10080 	}
10081 	traceData32 = detail;
10082 	RTC_TRACE();
10083 }
10084 
10085 void
10086 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10087 {
10088 	switch (component) {
10089 	case kIOPMLoginWindowProgress:
10090 		loginWindowData = data & kIOPMLoginWindowProgressMask;
10091 		break;
10092 	case kIOPMCoreDisplayProgress:
10093 		coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10094 		break;
10095 	case kIOPMCoreGraphicsProgress:
10096 		coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10097 		break;
10098 	default:
10099 		return;
10100 	}
10101 
10102 	DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10103 	RTC_TRACE();
10104 }
10105 
10106 void
10107 PMTraceWorker::tracePCIPowerChange(
10108 	change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10109 {
10110 	uint32_t    bitMask;
10111 	uint32_t    expectedFlag;
10112 
10113 	// Ignore PCI changes outside of system sleep/wake.
10114 	if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10115 	    (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10116 		return;
10117 	}
10118 
10119 	// Only record the WillChange transition when going to sleep,
10120 	// and the DidChange on the way up.
10121 	changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10122 	expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10123 	    kIOPMDomainWillChange : kIOPMDomainDidChange;
10124 	if (changeFlags != expectedFlag) {
10125 		return;
10126 	}
10127 
10128 	// Mark this device off in our bitfield
10129 	if (bitNum < kPMMaxRTCBitfieldSize) {
10130 		bitMask = (1 << bitNum);
10131 
10132 		if (kPowerChangeStart == type) {
10133 			traceData32 |= bitMask;
10134 			_LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n",
10135 			    service->getName(), bitNum, bitMask, traceData32);
10136 			owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10137 		} else {
10138 			traceData32 &= ~bitMask;
10139 			_LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10140 			    service->getName(), bitNum, bitMask, traceData32);
10141 			owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10142 		}
10143 
10144 		DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10145 		RTC_TRACE();
10146 	}
10147 }
10148 
10149 uint64_t
10150 PMTraceWorker::getPMStatusCode()
10151 {
10152 	return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10153 }
10154 
10155 uint8_t
10156 PMTraceWorker::getTracePhase()
10157 {
10158 	return tracePhase;
10159 }
10160 
10161 uint32_t
10162 PMTraceWorker::getTraceData()
10163 {
10164 	return traceData32;
10165 }
10166 
10167 // MARK: -
10168 // MARK: PMHaltWorker
10169 
10170 //******************************************************************************
10171 // PMHaltWorker Class
10172 //
10173 //******************************************************************************
10174 
10175 PMHaltWorker *
10176 PMHaltWorker::worker( void )
10177 {
10178 	PMHaltWorker *  me;
10179 	IOThread        thread;
10180 
10181 	do {
10182 		me = OSTypeAlloc( PMHaltWorker );
10183 		if (!me || !me->init()) {
10184 			break;
10185 		}
10186 
10187 		me->lock = IOLockAlloc();
10188 		if (!me->lock) {
10189 			break;
10190 		}
10191 
10192 		DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10193 		me->retain(); // thread holds extra retain
10194 		if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10195 			me->release();
10196 			break;
10197 		}
10198 		thread_deallocate(thread);
10199 		return me;
10200 	} while (false);
10201 
10202 	if (me) {
10203 		me->release();
10204 	}
10205 	return NULL;
10206 }
10207 
10208 void
10209 PMHaltWorker::free( void )
10210 {
10211 	DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10212 	if (lock) {
10213 		IOLockFree(lock);
10214 		lock = NULL;
10215 	}
10216 	return OSObject::free();
10217 }
10218 
10219 void
10220 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10221 {
10222 	PMHaltWorker * me = (PMHaltWorker *) arg;
10223 
10224 	IOLockLock( gPMHaltLock );
10225 	gPMHaltBusyCount++;
10226 	me->depth = gPMHaltDepth;
10227 	IOLockUnlock( gPMHaltLock );
10228 
10229 	while (me->depth >= 0) {
10230 		PMHaltWorker::work( me );
10231 
10232 		IOLockLock( gPMHaltLock );
10233 		if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10234 			// This is the last thread to finish work on this level,
10235 			// inform everyone to start working on next lower level.
10236 			gPMHaltDepth--;
10237 			me->depth = gPMHaltDepth;
10238 			gPMHaltIdleCount = 0;
10239 			thread_wakeup((event_t) &gPMHaltIdleCount);
10240 		} else {
10241 			// One or more threads are still working on this level,
10242 			// this thread must wait.
10243 			me->depth = gPMHaltDepth - 1;
10244 			do {
10245 				IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10246 			} while (me->depth != gPMHaltDepth);
10247 		}
10248 		IOLockUnlock( gPMHaltLock );
10249 	}
10250 
10251 	// No more work to do, terminate thread
10252 	DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10253 	thread_wakeup( &gPMHaltDepth );
10254 	me->release();
10255 }
10256 
10257 void
10258 PMHaltWorker::work( PMHaltWorker * me )
10259 {
10260 	OSSharedPtr<IOService>     service;
10261 	OSSet *         inner;
10262 	AbsoluteTime    startTime, elapsedTime;
10263 	UInt32          deltaTime;
10264 	bool            timeout;
10265 
10266 	while (true) {
10267 		timeout = false;
10268 
10269 		// Claim an unit of work from the shared pool
10270 		IOLockLock( gPMHaltLock );
10271 		inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10272 		if (inner) {
10273 			service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10274 			if (service) {
10275 				inner->removeObject(service.get());
10276 			}
10277 		}
10278 		IOLockUnlock( gPMHaltLock );
10279 		if (!service) {
10280 			break; // no more work at this depth
10281 		}
10282 		clock_get_uptime(&startTime);
10283 
10284 		if (!service->isInactive() &&
10285 		    service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10286 			IOLockLock(me->lock);
10287 			me->startTime = startTime;
10288 			me->service   = service.get();
10289 			me->timeout   = false;
10290 			IOLockUnlock(me->lock);
10291 
10292 			service->systemWillShutdown( gPMHaltMessageType);
10293 
10294 			// Wait for driver acknowledgement
10295 			IOLockLock(me->lock);
10296 			while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10297 				IOLockSleep(me->lock, me, THREAD_UNINT);
10298 			}
10299 			me->service = NULL;
10300 			timeout = me->timeout;
10301 			IOLockUnlock(me->lock);
10302 		}
10303 
10304 		deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10305 		if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10306 			LOG("%s driver %s (0x%llx) took %u ms\n",
10307 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10308 			    "PowerOff" : "Restart",
10309 			    service->getName(), service->getRegistryEntryID(),
10310 			    (uint32_t) deltaTime );
10311 			halt_log_enter("PowerOff/Restart handler completed",
10312 			    OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10313 			    elapsedTime);
10314 		}
10315 
10316 		me->visits++;
10317 	}
10318 }
10319 
10320 void
10321 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10322 {
10323 	UInt64          nano;
10324 	AbsoluteTime    startTime;
10325 	AbsoluteTime    endTime;
10326 
10327 	endTime = *now;
10328 
10329 	IOLockLock(me->lock);
10330 	if (me->service && !me->timeout) {
10331 		startTime = me->startTime;
10332 		nano = 0;
10333 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10334 			SUB_ABSOLUTETIME(&endTime, &startTime);
10335 			absolutetime_to_nanoseconds(endTime, &nano);
10336 		}
10337 		if (nano > 3000000000ULL) {
10338 			me->timeout = true;
10339 
10340 			halt_log_enter("PowerOff/Restart still waiting on handler",
10341 			    OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10342 			    endTime);
10343 			MSG("%s still waiting on %s\n",
10344 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?  "PowerOff" : "Restart",
10345 			    me->service->getName());
10346 		}
10347 	}
10348 	IOLockUnlock(me->lock);
10349 }
10350 
10351 //******************************************************************************
10352 // acknowledgeSystemWillShutdown
10353 //
10354 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10355 //******************************************************************************
10356 
10357 void
10358 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10359 {
10360 	PMHaltWorker            * worker;
10361 	OSSharedPtr<OSObject>     prop;
10362 
10363 	if (!from) {
10364 		return;
10365 	}
10366 
10367 	//DLOG("%s acknowledged\n", from->getName());
10368 	prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10369 	if (prop) {
10370 		worker = (PMHaltWorker *) prop.get();
10371 		IOLockLock(worker->lock);
10372 		from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10373 		thread_wakeup((event_t) worker);
10374 		IOLockUnlock(worker->lock);
10375 	} else {
10376 		DLOG("%s acknowledged without worker property\n",
10377 		    from->getName());
10378 	}
10379 }
10380 
10381 
10382 //******************************************************************************
10383 // notifySystemShutdown
10384 //
10385 // Notify all objects in PM tree that system will shutdown or restart
10386 //******************************************************************************
10387 
10388 static void
10389 notifySystemShutdown( IOService * root, uint32_t messageType )
10390 {
10391 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10392 	OSSharedPtr<IORegistryIterator>  iter;
10393 	IORegistryEntry *                entry;
10394 	IOService *                      node;
10395 	OSSet *                          inner;
10396 	OSSharedPtr<OSSet>               newInner;
10397 	PMHaltWorker *                   workers[kPMHaltMaxWorkers];
10398 	AbsoluteTime                     deadline;
10399 	unsigned int                     totalNodes = 0;
10400 	unsigned int                     depth;
10401 	unsigned int                     rootDepth;
10402 	unsigned int                     numWorkers;
10403 	unsigned int                     count;
10404 	int                              waitResult;
10405 	void *                           baseFunc;
10406 	bool                             ok;
10407 
10408 	DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10409 
10410 	baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10411 
10412 	// Iterate the entire PM tree starting from root
10413 
10414 	rootDepth = root->getDepth( gIOPowerPlane );
10415 	if (!rootDepth) {
10416 		goto done;
10417 	}
10418 
10419 	// debug - for repeated test runs
10420 	while (PMHaltWorker::metaClass->getInstanceCount()) {
10421 		IOSleep(1);
10422 	}
10423 
10424 	if (!gPMHaltArray) {
10425 		gPMHaltArray = OSArray::withCapacity(40);
10426 		if (!gPMHaltArray) {
10427 			goto done;
10428 		}
10429 	} else { // debug
10430 		gPMHaltArray->flushCollection();
10431 	}
10432 
10433 	if (!gPMHaltLock) {
10434 		gPMHaltLock = IOLockAlloc();
10435 		if (!gPMHaltLock) {
10436 			goto done;
10437 		}
10438 	}
10439 
10440 	if (!gPMHaltClientAcknowledgeKey) {
10441 		gPMHaltClientAcknowledgeKey =
10442 		    OSSymbol::withCStringNoCopy("PMShutdown");
10443 		if (!gPMHaltClientAcknowledgeKey) {
10444 			goto done;
10445 		}
10446 	}
10447 
10448 	gPMHaltMessageType = messageType;
10449 
10450 	// Depth-first walk of PM plane
10451 
10452 	iter = IORegistryIterator::iterateOver(
10453 		root, gIOPowerPlane, kIORegistryIterateRecursively);
10454 
10455 	if (iter) {
10456 		while ((entry = iter->getNextObject())) {
10457 			node = OSDynamicCast(IOService, entry);
10458 			if (!node) {
10459 				continue;
10460 			}
10461 
10462 			if (baseFunc ==
10463 			    OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10464 				continue;
10465 			}
10466 
10467 			depth = node->getDepth( gIOPowerPlane );
10468 			if (depth <= rootDepth) {
10469 				continue;
10470 			}
10471 
10472 			ok = false;
10473 
10474 			// adjust to zero based depth
10475 			depth -= (rootDepth + 1);
10476 
10477 			// gPMHaltArray is an array of containers, each container
10478 			// refers to nodes with the same depth.
10479 
10480 			count = gPMHaltArray->getCount();
10481 			while (depth >= count) {
10482 				// expand array and insert placeholders
10483 				gPMHaltArray->setObject(PLACEHOLDER);
10484 				count++;
10485 			}
10486 			count = gPMHaltArray->getCount();
10487 			if (depth < count) {
10488 				inner = (OSSet *)gPMHaltArray->getObject(depth);
10489 				if (inner == PLACEHOLDER) {
10490 					newInner = OSSet::withCapacity(40);
10491 					if (newInner) {
10492 						gPMHaltArray->replaceObject(depth, newInner.get());
10493 						inner = newInner.get();
10494 					}
10495 				}
10496 
10497 				// PM nodes that appear more than once in the tree will have
10498 				// the same depth, OSSet will refuse to add the node twice.
10499 				if (inner) {
10500 					ok = inner->setObject(node);
10501 				}
10502 			}
10503 			if (!ok) {
10504 				DLOG("Skipped PM node %s\n", node->getName());
10505 			}
10506 		}
10507 	}
10508 
10509 	// debug only
10510 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10511 		count = 0;
10512 		if (inner != PLACEHOLDER) {
10513 			count = inner->getCount();
10514 		}
10515 		DLOG("Nodes at depth %u = %u\n", i, count);
10516 	}
10517 
10518 	// strip placeholders (not all depths are populated)
10519 	numWorkers = 0;
10520 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10521 		if (inner == PLACEHOLDER) {
10522 			gPMHaltArray->removeObject(i);
10523 			continue;
10524 		}
10525 		count = inner->getCount();
10526 		if (count > numWorkers) {
10527 			numWorkers = count;
10528 		}
10529 		totalNodes += count;
10530 		i++;
10531 	}
10532 
10533 	if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10534 		goto done;
10535 	}
10536 
10537 	gPMHaltBusyCount = 0;
10538 	gPMHaltIdleCount = 0;
10539 	gPMHaltDepth = gPMHaltArray->getCount() - 1;
10540 
10541 	// Create multiple workers (and threads)
10542 
10543 	if (numWorkers > kPMHaltMaxWorkers) {
10544 		numWorkers = kPMHaltMaxWorkers;
10545 	}
10546 
10547 	DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10548 	    totalNodes, gPMHaltArray->getCount(), numWorkers);
10549 
10550 	for (unsigned int i = 0; i < numWorkers; i++) {
10551 		workers[i] = PMHaltWorker::worker();
10552 	}
10553 
10554 	// Wait for workers to exhaust all available work
10555 
10556 	IOLockLock(gPMHaltLock);
10557 	while (gPMHaltDepth >= 0) {
10558 		clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10559 
10560 		waitResult = IOLockSleepDeadline(
10561 			gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10562 		if (THREAD_TIMED_OUT == waitResult) {
10563 			AbsoluteTime now;
10564 			clock_get_uptime(&now);
10565 
10566 			IOLockUnlock(gPMHaltLock);
10567 			for (unsigned int i = 0; i < numWorkers; i++) {
10568 				if (workers[i]) {
10569 					PMHaltWorker::checkTimeout(workers[i], &now);
10570 				}
10571 			}
10572 			IOLockLock(gPMHaltLock);
10573 		}
10574 	}
10575 	IOLockUnlock(gPMHaltLock);
10576 
10577 	// Release all workers
10578 
10579 	for (unsigned int i = 0; i < numWorkers; i++) {
10580 		if (workers[i]) {
10581 			workers[i]->release();
10582 		}
10583 		// worker also retained by it's own thread
10584 	}
10585 
10586 done:
10587 	DLOG("%s done\n", __FUNCTION__);
10588 	return;
10589 }
10590 
10591 // MARK: -
10592 // MARK: Kernel Assertion
10593 
10594 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10595 
10596 IOPMDriverAssertionID
10597 IOPMrootDomain::createPMAssertion(
10598 	IOPMDriverAssertionType whichAssertionBits,
10599 	IOPMDriverAssertionLevel assertionLevel,
10600 	IOService *ownerService,
10601 	const char *ownerDescription)
10602 {
10603 	IOReturn            ret;
10604 	IOPMDriverAssertionID     newAssertion;
10605 
10606 	if (!pmAssertions) {
10607 		return 0;
10608 	}
10609 
10610 	ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10611 
10612 	if (kIOReturnSuccess == ret) {
10613 #if (DEVELOPMENT || DEBUG)
10614 		if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10615 			const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10616 			OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10617 			    serviceName, ownerDescription);
10618 		}
10619 #endif /* (DEVELOPMENT || DEBUG) */
10620 		return newAssertion;
10621 	} else {
10622 		return 0;
10623 	}
10624 }
10625 
10626 IOReturn
10627 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10628 {
10629 #if (DEVELOPMENT || DEBUG)
10630 	if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10631 		PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10632 		if (details) {
10633 			const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10634 			    details->ownerService->getName() : NULL;
10635 			const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10636 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10637 		} else {
10638 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10639 		}
10640 	}
10641 #endif /* (DEVELOPMENT || DEBUG) */
10642 	if (!pmAssertions) {
10643 		return kIOReturnInternalError;
10644 	}
10645 	return pmAssertions->releaseAssertion(releaseAssertion);
10646 }
10647 
10648 
10649 IOReturn
10650 IOPMrootDomain::setPMAssertionLevel(
10651 	IOPMDriverAssertionID assertionID,
10652 	IOPMDriverAssertionLevel assertionLevel)
10653 {
10654 	return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10655 }
10656 
10657 IOPMDriverAssertionLevel
10658 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10659 {
10660 	IOPMDriverAssertionType       sysLevels;
10661 
10662 	if (!pmAssertions || whichAssertion == 0) {
10663 		return kIOPMDriverAssertionLevelOff;
10664 	}
10665 
10666 	sysLevels = pmAssertions->getActivatedAssertions();
10667 
10668 	// Check that every bit set in argument 'whichAssertion' is asserted
10669 	// in the aggregate bits.
10670 	if ((sysLevels & whichAssertion) == whichAssertion) {
10671 		return kIOPMDriverAssertionLevelOn;
10672 	} else {
10673 		return kIOPMDriverAssertionLevelOff;
10674 	}
10675 }
10676 
10677 IOReturn
10678 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10679 {
10680 	if (!pmAssertions) {
10681 		return kIOReturnNotFound;
10682 	}
10683 
10684 	return pmAssertions->setUserAssertionLevels(inLevels);
10685 }
10686 
10687 IOReturn
10688 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10689 {
10690 	return gIOPMWorkLoop->runActionBlock(^{
10691 		if (_driverKitMatchingAssertionCount != 0) {
10692 		        _driverKitMatchingAssertionCount++;
10693 		        return kIOReturnSuccess;
10694 		} else {
10695 		        if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10696 		                // system going to sleep
10697 		                return kIOReturnBusy;
10698 			} else {
10699 		                // createPMAssertion is asynchronous.
10700 		                // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10701 		                // The assertion is used so that on release, we reevaluate all assertions
10702 		                _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10703 		                if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10704 		                        _driverKitMatchingAssertionCount = 1;
10705 		                        return kIOReturnSuccess;
10706 				} else {
10707 		                        return kIOReturnBusy;
10708 				}
10709 			}
10710 		}
10711 	});
10712 }
10713 
10714 void
10715 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10716 {
10717 	gIOPMWorkLoop->runActionBlock(^{
10718 		if (_driverKitMatchingAssertionCount != 0) {
10719 		        _driverKitMatchingAssertionCount--;
10720 		        if (_driverKitMatchingAssertionCount == 0) {
10721 		                releasePMAssertion(_driverKitMatchingAssertion);
10722 		                _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10723 			}
10724 		} else {
10725 		        panic("Over-release of driverkit matching assertion");
10726 		}
10727 		return kIOReturnSuccess;
10728 	});
10729 }
10730 
10731 bool
10732 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10733 {
10734 	if (pmAssertions) {
10735 		pmAssertions->publishProperties();
10736 	}
10737 	return IOService::serializeProperties(s);
10738 }
10739 
10740 OSSharedPtr<OSObject>
10741 IOPMrootDomain::copyProperty( const char * aKey) const
10742 {
10743 	OSSharedPtr<OSObject> obj;
10744 	obj = IOService::copyProperty(aKey);
10745 
10746 	if (obj) {
10747 		return obj;
10748 	}
10749 
10750 	if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10751 	    sizeof(kIOPMSleepWakeWdogRebootKey))) {
10752 		if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10753 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10754 		} else {
10755 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10756 		}
10757 	}
10758 
10759 	if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10760 	    sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10761 		if (swd_flags & SWD_VALID_LOGS) {
10762 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10763 		} else {
10764 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10765 		}
10766 	}
10767 
10768 	/*
10769 	 * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey'
10770 	 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10771 	 * issued by DisplayWrangler on darkwake.
10772 	 */
10773 	if (!strcmp(aKey, "DesktopMode")) {
10774 		if (desktopMode) {
10775 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10776 		} else {
10777 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10778 		}
10779 	}
10780 	if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10781 		if (displayIdleForDemandSleep) {
10782 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10783 		} else {
10784 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10785 		}
10786 	}
10787 
10788 	if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10789 		OSSharedPtr<OSArray> array;
10790 		WAKEEVENT_LOCK();
10791 		if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10792 			OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10793 			if (collection) {
10794 				array = OSDynamicPtrCast<OSArray>(collection);
10795 			}
10796 		}
10797 		WAKEEVENT_UNLOCK();
10798 		return os::move(array);
10799 	}
10800 
10801 	if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10802 		OSSharedPtr<OSArray> array;
10803 		IOLockLock(pmStatsLock);
10804 		if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10805 			OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10806 			if (collection) {
10807 				array = OSDynamicPtrCast<OSArray>(collection);
10808 			}
10809 		}
10810 		IOLockUnlock(pmStatsLock);
10811 		return os::move(array);
10812 	}
10813 
10814 	if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10815 		OSArray *idleSleepList = NULL;
10816 		gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10817 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10818 	}
10819 
10820 	if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10821 		OSArray *systemSleepList = NULL;
10822 		gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10823 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10824 	}
10825 
10826 	if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10827 		OSArray *idleSleepList = NULL;
10828 		gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10829 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10830 	}
10831 
10832 	if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10833 		OSArray *systemSleepList = NULL;
10834 		gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10835 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10836 	}
10837 	return NULL;
10838 }
10839 
10840 // MARK: -
10841 // MARK: Wake Event Reporting
10842 
10843 void
10844 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10845 {
10846 	WAKEEVENT_LOCK();
10847 	strlcpy(outBuf, gWakeReasonString, bufSize);
10848 	WAKEEVENT_UNLOCK();
10849 }
10850 
10851 void
10852 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10853 {
10854 	WAKEEVENT_LOCK();
10855 	strlcpy(outBuf, gShutdownReasonString, bufSize);
10856 	WAKEEVENT_UNLOCK();
10857 }
10858 
10859 //******************************************************************************
10860 // acceptSystemWakeEvents
10861 //
10862 // Private control for the acceptance of driver wake event claims.
10863 //******************************************************************************
10864 
10865 void
10866 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10867 {
10868 	bool logWakeReason = false;
10869 
10870 	WAKEEVENT_LOCK();
10871 	switch (control) {
10872 	case kAcceptSystemWakeEvents_Enable:
10873 		assert(_acceptSystemWakeEvents == false);
10874 		if (!_systemWakeEventsArray) {
10875 			_systemWakeEventsArray = OSArray::withCapacity(4);
10876 		}
10877 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10878 		if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10879 			gWakeReasonString[0] = '\0';
10880 			if (_systemWakeEventsArray) {
10881 				_systemWakeEventsArray->flushCollection();
10882 			}
10883 		}
10884 
10885 		// Remove stale WakeType property before system sleep
10886 		removeProperty(kIOPMRootDomainWakeTypeKey);
10887 		removeProperty(kIOPMRootDomainWakeReasonKey);
10888 		break;
10889 
10890 	case kAcceptSystemWakeEvents_Disable:
10891 		_acceptSystemWakeEvents = false;
10892 #if defined(XNU_TARGET_OS_OSX)
10893 		logWakeReason = (gWakeReasonString[0] != '\0');
10894 #else /* !defined(XNU_TARGET_OS_OSX) */
10895 		logWakeReason = gWakeReasonSysctlRegistered;
10896 #if DEVELOPMENT
10897 		static int panic_allowed = -1;
10898 
10899 		if ((panic_allowed == -1) &&
10900 		    (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10901 			panic_allowed = 0;
10902 		}
10903 
10904 		if (panic_allowed) {
10905 			size_t i = 0;
10906 			// Panic if wake reason is null or empty
10907 			for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10908 				if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10909 					break;
10910 				}
10911 			}
10912 			if (i >= strlen(gWakeReasonString)) {
10913 				panic("Wake reason is empty");
10914 			}
10915 		}
10916 #endif /* DEVELOPMENT */
10917 #endif /* !defined(XNU_TARGET_OS_OSX) */
10918 
10919 		// publish kIOPMRootDomainWakeReasonKey if not already set
10920 		if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10921 			setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10922 		}
10923 		break;
10924 
10925 	case kAcceptSystemWakeEvents_Reenable:
10926 		assert(_acceptSystemWakeEvents == false);
10927 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10928 		removeProperty(kIOPMRootDomainWakeReasonKey);
10929 		break;
10930 	}
10931 	WAKEEVENT_UNLOCK();
10932 
10933 	if (logWakeReason) {
10934 		MSG("system wake events: %s\n", gWakeReasonString);
10935 	}
10936 }
10937 
10938 //******************************************************************************
10939 // claimSystemWakeEvent
10940 //
10941 // For a driver to claim a device is the source/conduit of a system wake event.
10942 //******************************************************************************
10943 
10944 void
10945 IOPMrootDomain::claimSystemWakeEvent(
10946 	IOService *     device,
10947 	IOOptionBits    flags,
10948 	const char *    reason,
10949 	OSObject *      details )
10950 {
10951 	OSSharedPtr<const OSSymbol>     deviceName;
10952 	OSSharedPtr<OSNumber>           deviceRegId;
10953 	OSSharedPtr<OSNumber>           claimTime;
10954 	OSSharedPtr<OSData>             flagsData;
10955 	OSSharedPtr<OSString>           reasonString;
10956 	OSSharedPtr<OSDictionary>       dict;
10957 	uint64_t                        timestamp;
10958 	bool                            addWakeReason;
10959 
10960 	if (!device || !reason) {
10961 		return;
10962 	}
10963 
10964 	pmEventTimeStamp(&timestamp);
10965 
10966 	uint64_t args[3] = {};
10967 	strlcpy((char *)args, reason, sizeof(args));
10968 	kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
10969 
10970 	IOOptionBits        aotFlags = 0;
10971 	bool                needAOTEvaluate = FALSE;
10972 
10973 	if (kIOPMAOTModeAddEventFlags & _aotMode) {
10974 		// Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
10975 		if (strcmp("AOP.OutboxNotEmpty", reason) && strcmp("spu_gesture", reason)) {
10976 			flags |= kIOPMWakeEventAOTExit;
10977 		}
10978 	}
10979 
10980 #if DEVELOPMENT || DEBUG
10981 	if (_aotLingerTime && !strcmp("rtc", reason)) {
10982 		flags |= kIOPMWakeEventAOTPossibleExit;
10983 	}
10984 #endif /* DEVELOPMENT || DEBUG */
10985 
10986 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10987 	// Publishing the WakeType is serialized by the PM work loop
10988 	if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10989 		pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10990 		    (void *) _nextScheduledAlarmType.get());
10991 	}
10992 
10993 	// Workaround for the missing wake HID event
10994 	if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10995 		if (!strcmp("trackpadkeyboard", reason)) {
10996 			pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10997 			    (void *) gIOPMWakeTypeUserKey.get());
10998 		}
10999 	}
11000 #endif
11001 
11002 	deviceName   = device->copyName(gIOServicePlane);
11003 	deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11004 	claimTime    = OSNumber::withNumber(timestamp, 64);
11005 	flagsData    = OSData::withValue(flags);
11006 	reasonString = OSString::withCString(reason);
11007 	dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11008 	if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11009 		goto done;
11010 	}
11011 
11012 	dict->setObject(gIONameKey, deviceName.get());
11013 	dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11014 	dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11015 	dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11016 	dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11017 	if (details) {
11018 		dict->setObject(kIOPMWakeEventDetailsKey, details);
11019 	}
11020 
11021 	WAKEEVENT_LOCK();
11022 	addWakeReason = _acceptSystemWakeEvents;
11023 	if (_aotMode) {
11024 		IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11025 	}
11026 	aotFlags        = (kIOPMWakeEventAOTFlags & flags);
11027 	aotFlags        = (aotFlags & ~_aotPendingFlags);
11028 	needAOTEvaluate = false;
11029 	if (_aotNow && aotFlags) {
11030 		if (kIOPMWakeEventAOTPossibleExit & flags) {
11031 			_aotMetrics->possibleCount++;
11032 		}
11033 		if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11034 			_aotMetrics->confirmedPossibleCount++;
11035 		}
11036 		if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11037 			_aotMetrics->rejectedPossibleCount++;
11038 		}
11039 		if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11040 			_aotMetrics->expiredPossibleCount++;
11041 		}
11042 
11043 		_aotPendingFlags |= aotFlags;
11044 		addWakeReason     = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11045 		needAOTEvaluate   = _aotReadyToFullWake;
11046 	}
11047 	DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11048 	    reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11049 	    _aotNow, pmTracer->getTracePhase(), addWakeReason);
11050 
11051 #if DEVELOPMENT || DEBUG
11052 	if (addWakeReason) {
11053 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
11054 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11055 		    "Report System Wake Event",
11056 		    "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11057 		    reason,
11058 		    (int)flags,
11059 		    deviceName->getCStringNoCopy(),
11060 		    device->getRegistryEntryID()
11061 		    );
11062 	}
11063 #endif /* DEVELOPMENT || DEBUG */
11064 
11065 	if (!gWakeReasonSysctlRegistered) {
11066 		// Lazy registration until the platform driver stops registering
11067 		// the same name.
11068 		gWakeReasonSysctlRegistered = true;
11069 	}
11070 	if (addWakeReason) {
11071 		_systemWakeEventsArray->setObject(dict.get());
11072 		if (gWakeReasonString[0] != '\0') {
11073 			strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11074 		}
11075 		strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11076 	}
11077 
11078 	WAKEEVENT_UNLOCK();
11079 	if (needAOTEvaluate) {
11080 		// Call aotEvaluate() on PM work loop since it may call
11081 		// aotExit() which accesses PM state.
11082 		pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11083 	}
11084 
11085 done:
11086 	return;
11087 }
11088 
11089 //******************************************************************************
11090 // claimSystemBootEvent
11091 //
11092 // For a driver to claim a device is the source/conduit of a system boot event.
11093 //******************************************************************************
11094 
11095 void
11096 IOPMrootDomain::claimSystemBootEvent(
11097 	IOService *              device,
11098 	IOOptionBits             flags,
11099 	const char *             reason,
11100 	__unused OSObject *      details )
11101 {
11102 	if (!device || !reason) {
11103 		return;
11104 	}
11105 
11106 	DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11107 #if DEVELOPMENT || DEBUG
11108 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11109 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11110 	    "Report System Boot Device",
11111 	    "Reason: %s Flags: 0x%x Device: %s",
11112 	    reason,
11113 	    (int)flags,
11114 	    device->getName()
11115 	    );
11116 #endif /* DEVELOPMENT || DEBUG */
11117 	WAKEEVENT_LOCK();
11118 	if (!gBootReasonSysctlRegistered) {
11119 		// Lazy sysctl registration after setting gBootReasonString
11120 		strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11121 		os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11122 	}
11123 	WAKEEVENT_UNLOCK();
11124 }
11125 
11126 //******************************************************************************
11127 // claimSystemShutdownEvent
11128 //
11129 // For drivers to claim a system shutdown event on the ensuing boot.
11130 //******************************************************************************
11131 
11132 void
11133 IOPMrootDomain::claimSystemShutdownEvent(
11134 	IOService *              device,
11135 	IOOptionBits             flags,
11136 	const char *             reason,
11137 	__unused OSObject *      details )
11138 {
11139 	if (!device || !reason) {
11140 		return;
11141 	}
11142 
11143 	DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11144 #if DEVELOPMENT || DEBUG
11145 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11146 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11147 	    "Report System Shutdown Cause From Previous Boot",
11148 	    "Reason: %s Flags: 0x%x Device: %s",
11149 	    reason,
11150 	    (int)flags,
11151 	    device->getName()
11152 	    );
11153 #endif /* DEVELOPMENT || DEBUG */
11154 	WAKEEVENT_LOCK();
11155 	if (gShutdownReasonString[0] != '\0') {
11156 		strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11157 	}
11158 	strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11159 
11160 	gShutdownReasonSysctlRegistered = true;
11161 	WAKEEVENT_UNLOCK();
11162 }
11163 
11164 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11165 
11166 // MARK: -
11167 // MARK: PMSettingHandle
11168 
11169 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11170 
11171 void
11172 PMSettingHandle::free( void )
11173 {
11174 	if (pmso) {
11175 		pmso->clientHandleFreed();
11176 		pmso->release();
11177 		pmso = NULL;
11178 	}
11179 
11180 	OSObject::free();
11181 }
11182 
11183 // MARK: -
11184 // MARK: PMSettingObject
11185 
11186 #undef super
11187 #define super OSObject
11188 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11189 
11190 /*
11191  * Static constructor/initializer for PMSettingObject
11192  */
11193 PMSettingObject *PMSettingObject::pmSettingObject(
11194 	IOPMrootDomain                      * parent_arg,
11195 	IOPMSettingControllerCallback       handler_arg,
11196 	OSObject                            * target_arg,
11197 	uintptr_t                           refcon_arg,
11198 	uint32_t                            supportedPowerSources,
11199 	const OSSymbol *                    settings[],
11200 	OSObject                            * *handle_obj)
11201 {
11202 	uint32_t                            settingCount = 0;
11203 	PMSettingObject                     *pmso = NULL;
11204 	PMSettingHandle                     *pmsh = NULL;
11205 
11206 	if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11207 		return NULL;
11208 	}
11209 
11210 	// count OSSymbol entries in NULL terminated settings array
11211 	while (settings[settingCount]) {
11212 		settingCount++;
11213 	}
11214 	if (0 == settingCount) {
11215 		return NULL;
11216 	}
11217 
11218 	pmso = new PMSettingObject;
11219 	if (!pmso || !pmso->init()) {
11220 		goto fail;
11221 	}
11222 
11223 	pmsh = new PMSettingHandle;
11224 	if (!pmsh || !pmsh->init()) {
11225 		goto fail;
11226 	}
11227 
11228 	queue_init(&pmso->calloutQueue);
11229 	pmso->parent       = parent_arg;
11230 	pmso->func         = handler_arg;
11231 	pmso->target       = target_arg;
11232 	pmso->refcon       = refcon_arg;
11233 	pmso->settingCount = settingCount;
11234 
11235 	pmso->retain(); // handle holds a retain on pmso
11236 	pmsh->pmso = pmso;
11237 	pmso->pmsh = pmsh;
11238 
11239 	pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11240 	if (pmso->publishedFeatureID) {
11241 		for (unsigned int i = 0; i < settingCount; i++) {
11242 			// Since there is now at least one listener to this setting, publish
11243 			// PM root domain support for it.
11244 			parent_arg->publishPMSetting( settings[i],
11245 			    supportedPowerSources, &pmso->publishedFeatureID[i] );
11246 		}
11247 	}
11248 
11249 	*handle_obj = pmsh;
11250 	return pmso;
11251 
11252 fail:
11253 	if (pmso) {
11254 		pmso->release();
11255 	}
11256 	if (pmsh) {
11257 		pmsh->release();
11258 	}
11259 	return NULL;
11260 }
11261 
11262 void
11263 PMSettingObject::free( void )
11264 {
11265 	if (publishedFeatureID) {
11266 		for (const auto& featureID : publishedFeatureID) {
11267 			if (featureID) {
11268 				parent->removePublishedFeature( featureID );
11269 			}
11270 		}
11271 
11272 		publishedFeatureID = {};
11273 	}
11274 
11275 	super::free();
11276 }
11277 
11278 IOReturn
11279 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11280 {
11281 	return (*func)(target, type, object, refcon);
11282 }
11283 
11284 void
11285 PMSettingObject::clientHandleFreed( void )
11286 {
11287 	parent->deregisterPMSettingObject(this);
11288 }
11289 
11290 // MARK: -
11291 // MARK: PMAssertionsTracker
11292 
11293 //*********************************************************************************
11294 //*********************************************************************************
11295 //*********************************************************************************
11296 // class PMAssertionsTracker Implementation
11297 
11298 #define kAssertUniqueIDStart    500
11299 
11300 PMAssertionsTracker *
11301 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11302 {
11303 	PMAssertionsTracker    *me;
11304 
11305 	me = new PMAssertionsTracker;
11306 	if (!me || !me->init()) {
11307 		if (me) {
11308 			me->release();
11309 		}
11310 		return NULL;
11311 	}
11312 
11313 	me->owner = rootDomain;
11314 	me->issuingUniqueID = kAssertUniqueIDStart;
11315 	me->assertionsArray = OSArray::withCapacity(5);
11316 	me->assertionsKernel = 0;
11317 	me->assertionsUser = 0;
11318 	me->assertionsCombined = 0;
11319 	me->assertionsArrayLock = IOLockAlloc();
11320 	me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11321 
11322 	assert(me->assertionsArray);
11323 	assert(me->assertionsArrayLock);
11324 
11325 	return me;
11326 }
11327 
11328 /* tabulate
11329  * - Update assertionsKernel to reflect the state of all
11330  * assertions in the kernel.
11331  * - Update assertionsCombined to reflect both kernel & user space.
11332  */
11333 void
11334 PMAssertionsTracker::tabulate(void)
11335 {
11336 	int i;
11337 	int count;
11338 	const PMAssertStruct *_a = nullptr;
11339 	OSValueObject<PMAssertStruct> *_d = nullptr;
11340 
11341 	IOPMDriverAssertionType oldKernel = assertionsKernel;
11342 	IOPMDriverAssertionType oldCombined = assertionsCombined;
11343 
11344 	ASSERT_GATED();
11345 
11346 	assertionsKernel = 0;
11347 	assertionsCombined = 0;
11348 
11349 	if (!assertionsArray) {
11350 		return;
11351 	}
11352 
11353 	if ((count = assertionsArray->getCount())) {
11354 		for (i = 0; i < count; i++) {
11355 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11356 			if (_d) {
11357 				_a = _d->getBytesNoCopy();
11358 				if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11359 					assertionsKernel |= _a->assertionBits;
11360 				}
11361 			}
11362 		}
11363 	}
11364 
11365 	tabulateProducerCount++;
11366 	assertionsCombined = assertionsKernel | assertionsUser;
11367 
11368 	if ((assertionsKernel != oldKernel) ||
11369 	    (assertionsCombined != oldCombined)) {
11370 		owner->evaluateAssertions(assertionsCombined, oldCombined);
11371 	}
11372 }
11373 
11374 void
11375 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11376 {
11377 	AbsoluteTime now;
11378 	uint64_t     nsec;
11379 
11380 	if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11381 	    (assertStruct->assertCPUStartTime == 0)) {
11382 		return;
11383 	}
11384 
11385 	now = mach_absolute_time();
11386 	SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11387 	absolutetime_to_nanoseconds(now, &nsec);
11388 	assertStruct->assertCPUDuration += nsec;
11389 	assertStruct->assertCPUStartTime = 0;
11390 
11391 	if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11392 		maxAssertCPUDuration = assertStruct->assertCPUDuration;
11393 		maxAssertCPUEntryId = assertStruct->registryEntryID;
11394 	}
11395 }
11396 
11397 void
11398 PMAssertionsTracker::reportCPUBitAccounting( void )
11399 {
11400 	const PMAssertStruct *_a = nullptr;
11401 	OSValueObject<PMAssertStruct> *_d = nullptr;
11402 	int            i, count;
11403 	AbsoluteTime   now;
11404 	uint64_t       nsec;
11405 
11406 	ASSERT_GATED();
11407 
11408 	// Account for drivers that are still holding the CPU assertion
11409 	if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11410 		now = mach_absolute_time();
11411 		if ((count = assertionsArray->getCount())) {
11412 			for (i = 0; i < count; i++) {
11413 				_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11414 				if (_d) {
11415 					_a = _d->getBytesNoCopy();
11416 					if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11417 					    (_a->level == kIOPMDriverAssertionLevelOn) &&
11418 					    (_a->assertCPUStartTime != 0)) {
11419 						// Don't modify PMAssertStruct, leave that
11420 						// for updateCPUBitAccounting()
11421 						SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11422 						absolutetime_to_nanoseconds(now, &nsec);
11423 						nsec += _a->assertCPUDuration;
11424 						if (nsec > maxAssertCPUDuration) {
11425 							maxAssertCPUDuration = nsec;
11426 							maxAssertCPUEntryId = _a->registryEntryID;
11427 						}
11428 					}
11429 				}
11430 			}
11431 		}
11432 	}
11433 
11434 	if (maxAssertCPUDuration) {
11435 		DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11436 		    (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11437 	}
11438 
11439 	maxAssertCPUDuration = 0;
11440 	maxAssertCPUEntryId = 0;
11441 }
11442 
11443 void
11444 PMAssertionsTracker::publishProperties( void )
11445 {
11446 	OSSharedPtr<OSArray>             assertionsSummary;
11447 
11448 	if (tabulateConsumerCount != tabulateProducerCount) {
11449 		IOLockLock(assertionsArrayLock);
11450 
11451 		tabulateConsumerCount = tabulateProducerCount;
11452 
11453 		/* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11454 		 */
11455 		assertionsSummary = copyAssertionsArray();
11456 		if (assertionsSummary) {
11457 			owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11458 		} else {
11459 			owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11460 		}
11461 
11462 		/* Publish the IOPMrootDomain property "DriverPMAssertions"
11463 		 */
11464 		owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11465 
11466 		IOLockUnlock(assertionsArrayLock);
11467 	}
11468 }
11469 
11470 PMAssertStruct *
11471 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11472 {
11473 	PMAssertStruct      *_a = NULL;
11474 	OSValueObject<PMAssertStruct> *_d = nullptr;
11475 	int                 found = -1;
11476 	int                 count = 0;
11477 	int                 i = 0;
11478 
11479 	if (assertionsArray
11480 	    && (count = assertionsArray->getCount())) {
11481 		for (i = 0; i < count; i++) {
11482 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11483 			if (_d) {
11484 				_a = _d->getMutableBytesNoCopy();
11485 				if (_a && (_id == _a->id)) {
11486 					found = i;
11487 					break;
11488 				}
11489 			}
11490 		}
11491 	}
11492 
11493 	if (-1 == found) {
11494 		return NULL;
11495 	} else {
11496 		if (index) {
11497 			*index = found;
11498 		}
11499 		return _a;
11500 	}
11501 }
11502 
11503 /* PMAssertionsTracker::handleCreateAssertion
11504  * Perform assertion work on the PM workloop. Do not call directly.
11505  */
11506 IOReturn
11507 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11508 {
11509 	PMAssertStruct *assertStruct = nullptr;
11510 
11511 	ASSERT_GATED();
11512 
11513 	if (newAssertion) {
11514 		IOLockLock(assertionsArrayLock);
11515 		assertStruct = newAssertion->getMutableBytesNoCopy();
11516 		if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11517 		    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11518 			assertStruct->assertCPUStartTime = mach_absolute_time();
11519 		}
11520 		assertionsArray->setObject(newAssertion);
11521 		IOLockUnlock(assertionsArrayLock);
11522 		newAssertion->release();
11523 
11524 		tabulate();
11525 	}
11526 	return kIOReturnSuccess;
11527 }
11528 
11529 /* PMAssertionsTracker::createAssertion
11530  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11531  * appropiate.
11532  */
11533 IOReturn
11534 PMAssertionsTracker::createAssertion(
11535 	IOPMDriverAssertionType which,
11536 	IOPMDriverAssertionLevel level,
11537 	IOService *serviceID,
11538 	const char *whoItIs,
11539 	IOPMDriverAssertionID *outID)
11540 {
11541 	OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11542 	PMAssertStruct  track;
11543 
11544 	// Warning: trillions and trillions of created assertions may overflow the unique ID.
11545 	track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11546 	track.level = level;
11547 	track.assertionBits = which;
11548 
11549 	// NB: ownerString is explicitly managed by PMAssertStruct
11550 	// it will be released in `handleReleaseAssertion' below
11551 	track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11552 	track.ownerService = serviceID;
11553 	track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11554 	track.modifiedTime = 0;
11555 	pmEventTimeStamp(&track.createdTime);
11556 	track.assertCPUStartTime = 0;
11557 	track.assertCPUDuration = 0;
11558 
11559 	dataStore = OSValueObjectWithValue(track);
11560 	if (!dataStore) {
11561 		if (track.ownerString) {
11562 			track.ownerString->release();
11563 			track.ownerString = NULL;
11564 		}
11565 		return kIOReturnNoMemory;
11566 	}
11567 
11568 	*outID = track.id;
11569 
11570 	if (owner && owner->pmPowerStateQueue) {
11571 		// queue action is responsible for releasing dataStore
11572 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11573 	}
11574 
11575 	return kIOReturnSuccess;
11576 }
11577 
11578 /* PMAssertionsTracker::handleReleaseAssertion
11579  * Runs in PM workloop. Do not call directly.
11580  */
11581 IOReturn
11582 PMAssertionsTracker::handleReleaseAssertion(
11583 	IOPMDriverAssertionID _id)
11584 {
11585 	ASSERT_GATED();
11586 
11587 	int             index;
11588 	PMAssertStruct  *assertStruct = detailsForID(_id, &index);
11589 
11590 	if (!assertStruct) {
11591 		return kIOReturnNotFound;
11592 	}
11593 
11594 	IOLockLock(assertionsArrayLock);
11595 
11596 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11597 	    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11598 		updateCPUBitAccounting(assertStruct);
11599 	}
11600 
11601 	if (assertStruct->ownerString) {
11602 		assertStruct->ownerString->release();
11603 		assertStruct->ownerString = NULL;
11604 	}
11605 
11606 	assertionsArray->removeObject(index);
11607 	IOLockUnlock(assertionsArrayLock);
11608 
11609 	tabulate();
11610 	return kIOReturnSuccess;
11611 }
11612 
11613 /* PMAssertionsTracker::releaseAssertion
11614  * Releases an assertion and affects system behavior if appropiate.
11615  * Actual work happens on PM workloop.
11616  */
11617 IOReturn
11618 PMAssertionsTracker::releaseAssertion(
11619 	IOPMDriverAssertionID _id)
11620 {
11621 	if (owner && owner->pmPowerStateQueue) {
11622 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11623 	}
11624 	return kIOReturnSuccess;
11625 }
11626 
11627 /* PMAssertionsTracker::handleSetAssertionLevel
11628  * Runs in PM workloop. Do not call directly.
11629  */
11630 IOReturn
11631 PMAssertionsTracker::handleSetAssertionLevel(
11632 	IOPMDriverAssertionID    _id,
11633 	IOPMDriverAssertionLevel _level)
11634 {
11635 	PMAssertStruct      *assertStruct = detailsForID(_id, NULL);
11636 
11637 	ASSERT_GATED();
11638 
11639 	if (!assertStruct) {
11640 		return kIOReturnNotFound;
11641 	}
11642 
11643 	IOLockLock(assertionsArrayLock);
11644 	pmEventTimeStamp(&assertStruct->modifiedTime);
11645 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11646 	    (assertStruct->level != _level)) {
11647 		if (_level == kIOPMDriverAssertionLevelOn) {
11648 			assertStruct->assertCPUStartTime = mach_absolute_time();
11649 		} else {
11650 			updateCPUBitAccounting(assertStruct);
11651 		}
11652 	}
11653 	assertStruct->level = _level;
11654 	IOLockUnlock(assertionsArrayLock);
11655 
11656 	tabulate();
11657 	return kIOReturnSuccess;
11658 }
11659 
11660 /* PMAssertionsTracker::setAssertionLevel
11661  */
11662 IOReturn
11663 PMAssertionsTracker::setAssertionLevel(
11664 	IOPMDriverAssertionID    _id,
11665 	IOPMDriverAssertionLevel _level)
11666 {
11667 	if (owner && owner->pmPowerStateQueue) {
11668 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11669 		    (void *)(uintptr_t)_level, _id);
11670 	}
11671 
11672 	return kIOReturnSuccess;
11673 }
11674 
11675 IOReturn
11676 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11677 {
11678 	IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11679 
11680 	ASSERT_GATED();
11681 
11682 	if (new_user_levels != assertionsUser) {
11683 		DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11684 		assertionsUser = new_user_levels;
11685 	}
11686 
11687 	tabulate();
11688 	return kIOReturnSuccess;
11689 }
11690 
11691 IOReturn
11692 PMAssertionsTracker::setUserAssertionLevels(
11693 	IOPMDriverAssertionType new_user_levels)
11694 {
11695 	if (gIOPMWorkLoop) {
11696 		gIOPMWorkLoop->runAction(
11697 			OSMemberFunctionCast(
11698 				IOWorkLoop::Action,
11699 				this,
11700 				&PMAssertionsTracker::handleSetUserAssertionLevels),
11701 			this,
11702 			(void *) &new_user_levels, NULL, NULL, NULL);
11703 	}
11704 
11705 	return kIOReturnSuccess;
11706 }
11707 
11708 
11709 OSSharedPtr<OSArray>
11710 PMAssertionsTracker::copyAssertionsArray(void)
11711 {
11712 	int count;
11713 	int i;
11714 	OSSharedPtr<OSArray>     outArray = NULL;
11715 
11716 	if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11717 		goto exit;
11718 	}
11719 	outArray = OSArray::withCapacity(count);
11720 	if (!outArray) {
11721 		goto exit;
11722 	}
11723 
11724 	for (i = 0; i < count; i++) {
11725 		const PMAssertStruct *_a = nullptr;
11726 		OSValueObject<PMAssertStruct> *_d = nullptr;
11727 		OSSharedPtr<OSDictionary>    details;
11728 
11729 		_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11730 		if (_d && (_a = _d->getBytesNoCopy())) {
11731 			OSSharedPtr<OSNumber>        _n;
11732 
11733 			details = OSDictionary::withCapacity(7);
11734 			if (!details) {
11735 				continue;
11736 			}
11737 
11738 			outArray->setObject(details.get());
11739 
11740 			_n = OSNumber::withNumber(_a->id, 64);
11741 			if (_n) {
11742 				details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11743 			}
11744 			_n = OSNumber::withNumber(_a->createdTime, 64);
11745 			if (_n) {
11746 				details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11747 			}
11748 			_n = OSNumber::withNumber(_a->modifiedTime, 64);
11749 			if (_n) {
11750 				details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11751 			}
11752 			_n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11753 			if (_n) {
11754 				details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11755 			}
11756 			_n = OSNumber::withNumber(_a->level, 64);
11757 			if (_n) {
11758 				details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11759 			}
11760 			_n = OSNumber::withNumber(_a->assertionBits, 64);
11761 			if (_n) {
11762 				details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11763 			}
11764 
11765 			if (_a->ownerString) {
11766 				details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11767 			}
11768 		}
11769 	}
11770 
11771 exit:
11772 	return os::move(outArray);
11773 }
11774 
11775 IOPMDriverAssertionType
11776 PMAssertionsTracker::getActivatedAssertions(void)
11777 {
11778 	return assertionsCombined;
11779 }
11780 
11781 IOPMDriverAssertionLevel
11782 PMAssertionsTracker::getAssertionLevel(
11783 	IOPMDriverAssertionType type)
11784 {
11785 	// FIXME: unused and also wrong
11786 	if (type && ((type & assertionsKernel) == assertionsKernel)) {
11787 		return kIOPMDriverAssertionLevelOn;
11788 	} else {
11789 		return kIOPMDriverAssertionLevelOff;
11790 	}
11791 }
11792 
11793 //*********************************************************************************
11794 //*********************************************************************************
11795 //*********************************************************************************
11796 
11797 
11798 static void
11799 pmEventTimeStamp(uint64_t *recordTS)
11800 {
11801 	clock_sec_t     tsec;
11802 	clock_usec_t    tusec;
11803 
11804 	if (!recordTS) {
11805 		return;
11806 	}
11807 
11808 	// We assume tsec fits into 32 bits; 32 bits holds enough
11809 	// seconds for 136 years since the epoch in 1970.
11810 	clock_get_calendar_microtime(&tsec, &tusec);
11811 
11812 
11813 	// Pack the sec & microsec calendar time into a uint64_t, for fun.
11814 	*recordTS = 0;
11815 	*recordTS |= (uint32_t)tusec;
11816 	*recordTS |= ((uint64_t)tsec << 32);
11817 
11818 	return;
11819 }
11820 
11821 // MARK: -
11822 // MARK: IORootParent
11823 
11824 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11825 
11826 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11827 
11828 // The reason that root domain needs a root parent is to facilitate demand
11829 // sleep, since a power change from the root parent cannot be vetoed.
11830 //
11831 // The above statement is no longer true since root domain now performs
11832 // demand sleep using overrides. But root parent remains to avoid changing
11833 // the power tree stacking. Root parent is parked at the max power state.
11834 
11835 
11836 static IOPMPowerState patriarchPowerStates[2] =
11837 {
11838 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11839 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11840 };
11841 
11842 void
11843 IORootParent::initialize( void )
11844 {
11845 
11846 	gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11847 	gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11848 	gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11849 	gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11850 	gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11851 	gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11852 	gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11853 	gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11854 	gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11855 	gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11856 	gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11857 	gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11858 	gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11859 	gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11860 	gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11861 	gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11862 	gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11863 	gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11864 	gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11865 	gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11866 	gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11867 	gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11868 	gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11869 	gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11870 	gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11871 	gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11872 	gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11873 	gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11874 	gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11875 	gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11876 	gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11877 	gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11878 	gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11879 	gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11880 	gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11881 	gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11882 	gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11883 	gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11884 	gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11885 	gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11886 	gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11887 	gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11888 	gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11889 	gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11890 }
11891 
11892 bool
11893 IORootParent::start( IOService * nub )
11894 {
11895 	IOService::start(nub);
11896 	attachToParent( getRegistryRoot(), gIOPowerPlane );
11897 	PMinit();
11898 	registerPowerDriver(this, patriarchPowerStates, 2);
11899 	makeUsable();
11900 	return true;
11901 }
11902 
11903 void
11904 IORootParent::shutDownSystem( void )
11905 {
11906 }
11907 
11908 void
11909 IORootParent::restartSystem( void )
11910 {
11911 }
11912 
11913 void
11914 IORootParent::sleepSystem( void )
11915 {
11916 }
11917 
11918 void
11919 IORootParent::dozeSystem( void )
11920 {
11921 }
11922 
11923 void
11924 IORootParent::sleepToDoze( void )
11925 {
11926 }
11927 
11928 void
11929 IORootParent::wakeSystem( void )
11930 {
11931 }
11932 
11933 OSSharedPtr<OSObject>
11934 IORootParent::copyProperty( const char * aKey) const
11935 {
11936 	return IOService::copyProperty(aKey);
11937 }
11938 
11939 uint32_t
11940 IOPMrootDomain::getWatchdogTimeout()
11941 {
11942 	if (gSwdSleepWakeTimeout) {
11943 		gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11944 	}
11945 	if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11946 	    (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11947 		return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11948 	} else {
11949 		return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11950 	}
11951 }
11952 
11953 
11954 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11955 IOReturn
11956 IOPMrootDomain::restartWithStackshot()
11957 {
11958 	takeStackshot(true);
11959 
11960 	return kIOReturnSuccess;
11961 }
11962 
11963 void
11964 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11965 {
11966 	takeStackshot(wdogTrigger);
11967 }
11968 
11969 void
11970 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11971 {
11972 	switch (tracePhase) {
11973 	case kIOPMTracePointSleepStarted:
11974 		*phaseString = "kIOPMTracePointSleepStarted";
11975 		*description = "starting sleep";
11976 		break;
11977 
11978 	case kIOPMTracePointSleepApplications:
11979 		*phaseString = "kIOPMTracePointSleepApplications";
11980 		*description = "notifying applications";
11981 		break;
11982 
11983 	case kIOPMTracePointSleepPriorityClients:
11984 		*phaseString = "kIOPMTracePointSleepPriorityClients";
11985 		*description = "notifying clients about upcoming system capability changes";
11986 		break;
11987 
11988 	case kIOPMTracePointSleepWillChangeInterests:
11989 		*phaseString = "kIOPMTracePointSleepWillChangeInterests";
11990 		*description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11991 		break;
11992 
11993 	case kIOPMTracePointSleepPowerPlaneDrivers:
11994 		*phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11995 		*description = "calling power state change callbacks";
11996 		break;
11997 
11998 	case kIOPMTracePointSleepDidChangeInterests:
11999 		*phaseString = "kIOPMTracePointSleepDidChangeInterests";
12000 		*description = "calling rootDomain's clients about rootDomain's state changes";
12001 		break;
12002 
12003 	case kIOPMTracePointSleepCapabilityClients:
12004 		*phaseString = "kIOPMTracePointSleepCapabilityClients";
12005 		*description = "notifying clients about current system capabilities";
12006 		break;
12007 
12008 	case kIOPMTracePointSleepPlatformActions:
12009 		*phaseString = "kIOPMTracePointSleepPlatformActions";
12010 		*description = "calling Quiesce/Sleep action callbacks";
12011 		break;
12012 
12013 	case kIOPMTracePointSleepCPUs:
12014 	{
12015 		*phaseString = "kIOPMTracePointSleepCPUs";
12016 #if defined(__i386__) || defined(__x86_64__)
12017 		/*
12018 		 * We cannot use the getCPUNumber() method to get the cpu number, since
12019 		 * that cpu number is unrelated to the cpu number we need (we need the cpu
12020 		 * number as enumerated by the scheduler, NOT the CPU number enumerated
12021 		 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12022 		 * Instead, pass the Mach processor pointer associated with the current
12023 		 * shutdown target so its associated cpu_id can be used in
12024 		 * processor_to_datastring.
12025 		 */
12026 		if (currentShutdownTarget != NULL &&
12027 		    currentShutdownTarget->getMachProcessor() != NULL) {
12028 			const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12029 			    currentShutdownTarget->getMachProcessor());
12030 			*description = sbuf;
12031 		} else {
12032 			*description = "halting all non-boot CPUs";
12033 		}
12034 #else
12035 		*description = "halting all non-boot CPUs";
12036 #endif
12037 		break;
12038 	}
12039 	case kIOPMTracePointSleepPlatformDriver:
12040 		*phaseString = "kIOPMTracePointSleepPlatformDriver";
12041 		*description = "executing platform specific code";
12042 		break;
12043 
12044 	case kIOPMTracePointHibernate:
12045 		*phaseString = "kIOPMTracePointHibernate";
12046 		*description = "writing the hibernation image";
12047 		break;
12048 
12049 	case kIOPMTracePointSystemSleep:
12050 		*phaseString = "kIOPMTracePointSystemSleep";
12051 		*description = "in EFI/Bootrom after last point of entry to sleep";
12052 		break;
12053 
12054 	case kIOPMTracePointWakePlatformDriver:
12055 		*phaseString = "kIOPMTracePointWakePlatformDriver";
12056 		*description = "executing platform specific code";
12057 		break;
12058 
12059 
12060 	case kIOPMTracePointWakePlatformActions:
12061 		*phaseString = "kIOPMTracePointWakePlatformActions";
12062 		*description = "calling Wake action callbacks";
12063 		break;
12064 
12065 	case kIOPMTracePointWakeCPUs:
12066 		*phaseString = "kIOPMTracePointWakeCPUs";
12067 		*description = "starting non-boot CPUs";
12068 		break;
12069 
12070 	case kIOPMTracePointWakeWillPowerOnClients:
12071 		*phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12072 		*description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12073 		break;
12074 
12075 	case kIOPMTracePointWakeWillChangeInterests:
12076 		*phaseString = "kIOPMTracePointWakeWillChangeInterests";
12077 		*description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12078 		break;
12079 
12080 	case kIOPMTracePointWakeDidChangeInterests:
12081 		*phaseString = "kIOPMTracePointWakeDidChangeInterests";
12082 		*description = "calling rootDomain's clients about completed rootDomain's state changes";
12083 		break;
12084 
12085 	case kIOPMTracePointWakePowerPlaneDrivers:
12086 		*phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12087 		*description = "calling power state change callbacks";
12088 		break;
12089 
12090 	case kIOPMTracePointWakeCapabilityClients:
12091 		*phaseString = "kIOPMTracePointWakeCapabilityClients";
12092 		*description = "informing clients about current system capabilities";
12093 		break;
12094 
12095 	case kIOPMTracePointWakeApplications:
12096 		*phaseString = "kIOPMTracePointWakeApplications";
12097 		*description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12098 		break;
12099 
12100 	case kIOPMTracePointDarkWakeEntry:
12101 		*phaseString = "kIOPMTracePointDarkWakeEntry";
12102 		*description = "entering darkwake on way to sleep";
12103 		break;
12104 
12105 	case kIOPMTracePointDarkWakeExit:
12106 		*phaseString = "kIOPMTracePointDarkWakeExit";
12107 		*description = "entering fullwake from darkwake";
12108 		break;
12109 
12110 	default:
12111 		*phaseString = NULL;
12112 		*description = NULL;
12113 	}
12114 }
12115 
12116 void
12117 IOPMrootDomain::saveFailureData2File()
12118 {
12119 	unsigned int len = 0;
12120 	char  failureStr[512];
12121 	errno_t error;
12122 	char *outbuf;
12123 	OSNumber *statusCode;
12124 	uint64_t pmStatusCode = 0;
12125 	uint32_t phaseData = 0;
12126 	uint32_t phaseDetail = 0;
12127 	bool efiFailure = false;
12128 
12129 	OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12130 	statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12131 	if (statusCode) {
12132 		pmStatusCode = statusCode->unsigned64BitValue();
12133 		phaseData = pmStatusCode & 0xFFFFFFFF;
12134 		phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12135 		if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12136 			LOG("Sleep Wake failure in EFI\n");
12137 			efiFailure = true;
12138 			failureStr[0] = 0;
12139 			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);
12140 			len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12141 		}
12142 	}
12143 
12144 	if (!efiFailure) {
12145 		if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12146 			swd_flags |= SWD_BOOT_BY_SW_WDOG;
12147 			PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12148 			// dump panic will handle saving nvram data
12149 			return;
12150 		}
12151 
12152 		/* Keeping this around for capturing data during power
12153 		 * button press */
12154 
12155 		if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12156 			DLOG("No sleep wake failure string\n");
12157 			return;
12158 		}
12159 		if (len == 0) {
12160 			DLOG("Ignoring zero byte SleepWake failure string\n");
12161 			goto exit;
12162 		}
12163 
12164 		// if PMStatus code is zero, delete stackshot and return
12165 		if (statusCode) {
12166 			if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12167 				// there was no sleep wake failure
12168 				// this can happen if delete stackshot was called
12169 				// before take stackshot completed. Let us delete any
12170 				// sleep wake failure data in nvram
12171 				DLOG("Deleting stackshot on successful wake\n");
12172 				deleteStackshot();
12173 				return;
12174 			}
12175 		}
12176 
12177 		if (len > sizeof(failureStr)) {
12178 			len = sizeof(failureStr);
12179 		}
12180 		failureStr[0] = 0;
12181 		PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12182 	}
12183 	if (failureStr[0] != 0) {
12184 		error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12185 		if (error) {
12186 			DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12187 		} else {
12188 			DLOG("Saved SleepWake failure string to file.\n");
12189 		}
12190 	}
12191 
12192 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12193 		goto exit;
12194 	}
12195 
12196 	if (swd_buffer) {
12197 		unsigned int len = 0;
12198 		errno_t error;
12199 		char nvram_var_name_buffer[20];
12200 		unsigned int concat_len = 0;
12201 		swd_hdr      *hdr = NULL;
12202 
12203 
12204 		hdr = (swd_hdr *)swd_buffer;
12205 		outbuf = (char *)hdr + hdr->spindump_offset;
12206 		OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12207 
12208 		for (int i = 0; i < 8; i++) {
12209 			snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12210 			if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12211 				LOG("No SleepWake blob to read beyond chunk %d\n", i);
12212 				break;
12213 			}
12214 			if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12215 				PERemoveNVRAMProperty(nvram_var_name_buffer);
12216 				LOG("Could not read the property :-(\n");
12217 				break;
12218 			}
12219 			PERemoveNVRAMProperty(nvram_var_name_buffer);
12220 			concat_len += len;
12221 		}
12222 		LOG("Concatenated length for the SWD blob %d\n", concat_len);
12223 
12224 		if (concat_len) {
12225 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12226 			if (error) {
12227 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12228 			} else {
12229 				LOG("Saved SleepWake zipped data to file.\n");
12230 			}
12231 		} else {
12232 			// There is a sleep wake failure string but no stackshot
12233 			// Write a placeholder stacks file so that swd runs
12234 			snprintf(outbuf, 20, "%s", "No stackshot data\n");
12235 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12236 			if (error) {
12237 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12238 			} else {
12239 				LOG("Saved SleepWake zipped data to file.\n");
12240 			}
12241 		}
12242 	} else {
12243 		LOG("No buffer allocated to save failure stackshot\n");
12244 	}
12245 
12246 
12247 	gRootDomain->swd_lock = 0;
12248 exit:
12249 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12250 	return;
12251 }
12252 
12253 
12254 void
12255 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12256 {
12257 	OSSharedPtr<IORegistryIterator>    iter;
12258 	OSSharedPtr<const OSSymbol>        kextName = NULL;
12259 	IORegistryEntry *       entry;
12260 	IOService *             node;
12261 	bool                    nodeFound = false;
12262 
12263 	const void *            callMethod = NULL;
12264 	const char *            objectName = NULL;
12265 	const char *            phaseString = NULL;
12266 	const char *            phaseDescription = NULL;
12267 	uint64_t                delta;
12268 
12269 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12270 	uint32_t tracePhase = pmTracer->getTracePhase();
12271 
12272 	*thread = NULL;
12273 
12274 	delta = get_watchdog_elapsed_time();
12275 	if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12276 		snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12277 	} else {
12278 		snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12279 	}
12280 	tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12281 
12282 	if (notifierThread) {
12283 		if (notifier && (notifier->identifier)) {
12284 			objectName = notifier->identifier->getCStringNoCopy();
12285 		}
12286 		*thread = notifierThread;
12287 	} else {
12288 		iter = IORegistryIterator::iterateOver(
12289 			getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12290 
12291 		if (iter) {
12292 			while ((entry = iter->getNextObject())) {
12293 				node = OSDynamicCast(IOService, entry);
12294 				if (!node) {
12295 					continue;
12296 				}
12297 				if (OSDynamicCast(IOPowerConnection, node)) {
12298 					continue;
12299 				}
12300 
12301 				if (node->getBlockingDriverCall(thread, &callMethod)) {
12302 					nodeFound = true;
12303 					break;
12304 				}
12305 			}
12306 		}
12307 		if (nodeFound) {
12308 			kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12309 			if (kextName) {
12310 				objectName = kextName->getCStringNoCopy();
12311 			}
12312 		}
12313 	}
12314 	if (phaseDescription) {
12315 		strlcat(failureStr, " while ", strLen);
12316 		strlcat(failureStr, phaseDescription, strLen);
12317 		strlcat(failureStr, ".", strLen);
12318 	}
12319 	if (objectName) {
12320 		strlcat(failureStr, " Suspected bundle: ", strLen);
12321 		strlcat(failureStr, objectName, strLen);
12322 		strlcat(failureStr, ".", strLen);
12323 	}
12324 	if (*thread) {
12325 		char threadName[40];
12326 		snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12327 		strlcat(failureStr, threadName, strLen);
12328 	}
12329 
12330 	DLOG("%s\n", failureStr);
12331 }
12332 
12333 struct swd_stackshot_compressed_data {
12334 	z_output_func   zoutput;
12335 	size_t                  zipped;
12336 	uint64_t                totalbytes;
12337 	uint64_t                lastpercent;
12338 	IOReturn                error;
12339 	unsigned                outremain;
12340 	unsigned                outlen;
12341 	unsigned                writes;
12342 	Bytef *                 outbuf;
12343 };
12344 struct swd_stackshot_compressed_data swd_zip_var = { };
12345 
12346 static void *
12347 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12348 {
12349 	void *result;
12350 	LOG("Alloc in zipping %d items of size %d\n", items, size);
12351 
12352 	result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12353 	swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12354 	LOG("Offset %zu\n", swd_zs_zoffset);
12355 	return result;
12356 }
12357 
12358 static int
12359 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12360 {
12361 	unsigned len;
12362 
12363 	len = strm->avail_in;
12364 
12365 	if (len > size) {
12366 		len = size;
12367 	}
12368 	if (len == 0) {
12369 		return 0;
12370 	}
12371 
12372 	if (strm->next_in != (Bytef *) strm) {
12373 		memcpy(buf, strm->next_in, len);
12374 	} else {
12375 		bzero(buf, len);
12376 	}
12377 
12378 	strm->adler = z_crc32(strm->adler, buf, len);
12379 
12380 	strm->avail_in -= len;
12381 	strm->next_in  += len;
12382 	strm->total_in += len;
12383 
12384 	return (int)len;
12385 }
12386 
12387 static int
12388 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12389 {
12390 	unsigned int i = 0;
12391 	// if outlen > max size don't add to the buffer
12392 	assert(buf != NULL);
12393 	if (strm && buf) {
12394 		if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12395 			LOG("No space to GZIP... not writing to NVRAM\n");
12396 			return len;
12397 		}
12398 	}
12399 	for (i = 0; i < len; i++) {
12400 		*(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12401 	}
12402 	swd_zip_var.outlen += len;
12403 	return len;
12404 }
12405 
12406 static void
12407 swd_zs_free(void * __unused ref, void * __unused ptr)
12408 {
12409 }
12410 
12411 static int
12412 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12413 {
12414 	int wbits = 12;
12415 	int memlevel = 3;
12416 
12417 	if (((unsigned int) numBytes) != numBytes) {
12418 		return 0;
12419 	}
12420 
12421 	if (!swd_zs.zalloc) {
12422 		swd_zs.zalloc = swd_zs_alloc;
12423 		swd_zs.zfree = swd_zs_free;
12424 		if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12425 			// allocation failed
12426 			bzero(&swd_zs, sizeof(swd_zs));
12427 			// swd_zs_zoffset = 0;
12428 		} else {
12429 			LOG("PMRD inited the zlib allocation routines\n");
12430 		}
12431 	}
12432 
12433 	swd_zip_var.zipped = 0;
12434 	swd_zip_var.totalbytes = 0; // should this be the max that we have?
12435 	swd_zip_var.lastpercent = 0;
12436 	swd_zip_var.error = kIOReturnSuccess;
12437 	swd_zip_var.outremain = 0;
12438 	swd_zip_var.outlen = 0;
12439 	swd_zip_var.writes = 0;
12440 	swd_zip_var.outbuf = (Bytef *)outPtr;
12441 
12442 	swd_zip_var.totalbytes = numBytes;
12443 
12444 	swd_zs.avail_in = 0;
12445 	swd_zs.next_in = NULL;
12446 	swd_zs.avail_out = 0;
12447 	swd_zs.next_out = NULL;
12448 
12449 	deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12450 
12451 	z_stream *zs;
12452 	int zr;
12453 	zs = &swd_zs;
12454 
12455 	while (swd_zip_var.error >= 0) {
12456 		if (!zs->avail_in) {
12457 			zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12458 			zs->avail_in = (unsigned int) numBytes;
12459 		}
12460 		if (!zs->avail_out) {
12461 			zs->next_out = (Bytef *)zs;
12462 			zs->avail_out = UINT32_MAX;
12463 		}
12464 		zr = deflate(zs, Z_NO_FLUSH);
12465 		if (Z_STREAM_END == zr) {
12466 			break;
12467 		}
12468 		if (zr != Z_OK) {
12469 			LOG("ZERR %d\n", zr);
12470 			swd_zip_var.error = zr;
12471 		} else {
12472 			if (zs->total_in == numBytes) {
12473 				break;
12474 			}
12475 		}
12476 	}
12477 
12478 	//now flush the stream
12479 	while (swd_zip_var.error >= 0) {
12480 		if (!zs->avail_out) {
12481 			zs->next_out = (Bytef *)zs;
12482 			zs->avail_out = UINT32_MAX;
12483 		}
12484 		zr = deflate(zs, Z_FINISH);
12485 		if (Z_STREAM_END == zr) {
12486 			break;
12487 		}
12488 		if (zr != Z_OK) {
12489 			LOG("ZERR %d\n", zr);
12490 			swd_zip_var.error = zr;
12491 		} else {
12492 			if (zs->total_in == numBytes) {
12493 				LOG("Total output size %d\n", swd_zip_var.outlen);
12494 				break;
12495 			}
12496 		}
12497 	}
12498 
12499 	return swd_zip_var.outlen;
12500 }
12501 
12502 void
12503 IOPMrootDomain::deleteStackshot()
12504 {
12505 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12506 		// takeStackshot hasn't completed
12507 		return;
12508 	}
12509 	LOG("Deleting any sleepwake failure data in nvram\n");
12510 
12511 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12512 	char nvram_var_name_buf[20];
12513 	for (int i = 0; i < 8; i++) {
12514 		snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12515 		if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12516 			LOG("Removing %s returned false\n", nvram_var_name_buf);
12517 		}
12518 	}
12519 	// force NVRAM sync
12520 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12521 		DLOG("Failed to force nvram sync\n");
12522 	}
12523 	gRootDomain->swd_lock = 0;
12524 }
12525 
12526 void
12527 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12528 {
12529 	swd_hdr *                hdr = NULL;
12530 	int                      cnt = 0;
12531 	int                      max_cnt;
12532 	pid_t                    pid = 0;
12533 	kern_return_t            kr = KERN_SUCCESS;
12534 	uint64_t                 flags;
12535 
12536 	char *                   dstAddr;
12537 	uint32_t                 size;
12538 	uint32_t                 bytesRemaining;
12539 	unsigned                 bytesWritten = 0;
12540 
12541 	char                     failureStr[512];
12542 	thread_t                 thread = NULL;
12543 	const char *             swfPanic = "swfPanic";
12544 
12545 	uint32_t                 bufSize;
12546 	int                      success = 0;
12547 
12548 #if defined(__i386__) || defined(__x86_64__)
12549 	const bool               concise = false;
12550 #else
12551 	const bool               concise = true;
12552 #endif
12553 
12554 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12555 		return;
12556 	}
12557 
12558 	failureStr[0] = 0;
12559 	if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12560 		return;
12561 	}
12562 
12563 	if (wdogTrigger) {
12564 		getFailureData(&thread, failureStr, sizeof(failureStr));
12565 
12566 		if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12567 			goto skip_stackshot;
12568 		}
12569 	} else {
12570 		AbsoluteTime now;
12571 		uint64_t nsec;
12572 		clock_get_uptime(&now);
12573 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12574 		absolutetime_to_nanoseconds(now, &nsec);
12575 		snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12576 	}
12577 
12578 	if (swd_buffer == NULL) {
12579 		sleepWakeDebugMemAlloc();
12580 		if (swd_buffer == NULL) {
12581 			return;
12582 		}
12583 	}
12584 	hdr = (swd_hdr *)swd_buffer;
12585 	bufSize = hdr->alloc_size;
12586 
12587 	dstAddr = (char*)hdr + hdr->spindump_offset;
12588 	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;
12589 
12590 	/* If not wdogTrigger only take kernel tasks stackshot
12591 	 */
12592 	if (wdogTrigger) {
12593 		pid = -1;
12594 		max_cnt = 3;
12595 	} else {
12596 		pid = 0;
12597 		max_cnt = 2;
12598 	}
12599 
12600 	/* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12601 	 * If we run out of space, take stackshot with only kernel task
12602 	 */
12603 	while (success == 0 && cnt < max_cnt) {
12604 		bytesRemaining = bufSize - hdr->spindump_offset;
12605 		cnt++;
12606 		DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12607 
12608 		size = bytesRemaining;
12609 		kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12610 		DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12611 		    kr, pid, size, flags, bytesWritten);
12612 		if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12613 			if (pid == -1) {
12614 				pid = 0;
12615 			} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12616 				flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12617 			} else {
12618 				LOG("Insufficient buffer size for only kernel task\n");
12619 				break;
12620 			}
12621 		}
12622 		if (kr == KERN_SUCCESS) {
12623 			if (bytesWritten == 0) {
12624 				MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12625 				continue;
12626 			}
12627 			bytesRemaining -= bytesWritten;
12628 			hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12629 
12630 			memset(hdr->reason, 0x20, sizeof(hdr->reason));
12631 
12632 			// Compress stackshot and save to NVRAM
12633 			{
12634 				char *outbuf = (char *)swd_compressed_buffer;
12635 				int outlen = 0;
12636 				int num_chunks = 0;
12637 				int max_chunks = 0;
12638 				int leftover = 0;
12639 				char nvram_var_name_buffer[20];
12640 
12641 				outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12642 
12643 				if (outlen) {
12644 					max_chunks = outlen / (2096 - 200);
12645 					leftover = outlen % (2096 - 200);
12646 
12647 					if (max_chunks < 8) {
12648 						for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12649 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12650 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12651 								LOG("Failed to update NVRAM %d\n", num_chunks);
12652 								break;
12653 							}
12654 						}
12655 						if (leftover) {
12656 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12657 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12658 								LOG("Failed to update NVRAM with leftovers\n");
12659 							}
12660 						}
12661 						success = 1;
12662 						LOG("Successfully saved stackshot to NVRAM\n");
12663 					} else {
12664 						if (pid == -1) {
12665 							LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12666 							pid = 0;
12667 						} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12668 							LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12669 							flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12670 						} else {
12671 							LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12672 							break;
12673 						}
12674 					}
12675 				}
12676 			}
12677 		}
12678 	}
12679 
12680 	if (failureStr[0]) {
12681 		// append sleep-wake failure code
12682 		char traceCode[80];
12683 		snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12684 		    pmTracer->getTraceData(), pmTracer->getTracePhase());
12685 		strlcat(failureStr, traceCode, sizeof(failureStr));
12686 		if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12687 			DLOG("Failed to write SleepWake failure string\n");
12688 		}
12689 	}
12690 
12691 	// force NVRAM sync
12692 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12693 		DLOG("Failed to force nvram sync\n");
12694 	}
12695 
12696 skip_stackshot:
12697 	if (wdogTrigger) {
12698 		if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12699 			if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12700 				// If current boot is due to this watch dog trigger restart in previous boot,
12701 				// then don't trigger again until at least 1 successful sleep & wake.
12702 				if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12703 					LOG("Shutting down due to repeated Sleep/Wake failures\n");
12704 					updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12705 					PEHaltRestart(kPEHaltCPU);
12706 					return;
12707 				}
12708 			}
12709 			if (gSwdPanic == 0) {
12710 				LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12711 				updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12712 				PEHaltRestart(kPERestartCPU);
12713 			}
12714 		}
12715 		if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12716 			DLOG("Failed to write SleepWake failure panic key\n");
12717 		}
12718 #if defined(__x86_64__)
12719 		if (thread) {
12720 			panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12721 		} else
12722 #endif /* defined(__x86_64__) */
12723 		{
12724 			panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12725 		}
12726 	} else {
12727 		gRootDomain->swd_lock = 0;
12728 		return;
12729 	}
12730 }
12731 
12732 void
12733 IOPMrootDomain::sleepWakeDebugMemAlloc()
12734 {
12735 	vm_size_t    size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12736 
12737 	swd_hdr      *hdr = NULL;
12738 	void         *bufPtr = NULL;
12739 
12740 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12741 
12742 
12743 	if (kIOSleepWakeWdogOff & gIOKitDebug) {
12744 		return;
12745 	}
12746 
12747 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12748 		return;
12749 	}
12750 
12751 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12752 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12753 		size);
12754 	if (memDesc == NULL) {
12755 		DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12756 		goto exit;
12757 	}
12758 
12759 	bufPtr = memDesc->getBytesNoCopy();
12760 
12761 	// Carve out memory for zlib routines
12762 	swd_zs_zmem = (vm_offset_t)bufPtr;
12763 	bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12764 
12765 	// Carve out memory for compressed stackshots
12766 	swd_compressed_buffer = bufPtr;
12767 	bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12768 
12769 	// Remaining is used for holding stackshot
12770 	hdr = (swd_hdr *)bufPtr;
12771 	memset(hdr, 0, sizeof(swd_hdr));
12772 
12773 	hdr->signature = SWD_HDR_SIGNATURE;
12774 	hdr->alloc_size = SWD_STACKSHOT_SIZE;
12775 
12776 	hdr->spindump_offset = sizeof(swd_hdr);
12777 	swd_buffer = (void *)hdr;
12778 	swd_memDesc = os::move(memDesc);
12779 	DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12780 
12781 exit:
12782 	gRootDomain->swd_lock = 0;
12783 }
12784 
12785 void
12786 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12787 {
12788 #if UNUSED
12789 	vm_size_t    size = SWD_SPINDUMP_SIZE;
12790 
12791 	swd_hdr      *hdr = NULL;
12792 
12793 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12794 
12795 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12796 		return;
12797 	}
12798 
12799 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12800 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12801 		SWD_SPINDUMP_SIZE);
12802 
12803 	if (memDesc == NULL) {
12804 		DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12805 		goto exit;
12806 	}
12807 
12808 
12809 	hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12810 	memset(hdr, 0, sizeof(swd_hdr));
12811 
12812 	hdr->signature = SWD_HDR_SIGNATURE;
12813 	hdr->alloc_size = size;
12814 
12815 	hdr->spindump_offset = sizeof(swd_hdr);
12816 	swd_spindump_buffer = (void *)hdr;
12817 	swd_spindump_memDesc = os::move(memDesc);
12818 
12819 exit:
12820 	gRootDomain->swd_lock = 0;
12821 #endif /* UNUSED */
12822 }
12823 
12824 void
12825 IOPMrootDomain::sleepWakeDebugEnableWdog()
12826 {
12827 }
12828 
12829 bool
12830 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12831 {
12832 	return !systemBooting && !systemShutdown && !gWillShutdown;
12833 }
12834 
12835 void
12836 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12837 {
12838 	swd_hdr *hdr = NULL;
12839 	errno_t error = EIO;
12840 
12841 	if (swd_spindump_buffer && gSpinDumpBufferFull) {
12842 		hdr = (swd_hdr *)swd_spindump_buffer;
12843 
12844 		error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12845 		    (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12846 
12847 		if (error) {
12848 			return;
12849 		}
12850 
12851 		sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12852 		    (char*)hdr + offsetof(swd_hdr, UUID),
12853 		    sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12854 
12855 		gSpinDumpBufferFull = false;
12856 	}
12857 }
12858 
12859 errno_t
12860 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12861 {
12862 	struct vnode         *vp = NULL;
12863 	vfs_context_t        ctx = vfs_context_create(vfs_context_current());
12864 	kauth_cred_t         cred = vfs_context_ucred(ctx);
12865 	struct vnode_attr    va;
12866 	errno_t      error = EIO;
12867 
12868 	if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12869 	    S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12870 		LOG("Failed to open the file %s\n", name);
12871 		swd_flags |= SWD_FILEOP_ERROR;
12872 		goto exit;
12873 	}
12874 	VATTR_INIT(&va);
12875 	VATTR_WANTED(&va, va_nlink);
12876 	/* Don't dump to non-regular files or files with links. */
12877 	if (vp->v_type != VREG ||
12878 	    vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12879 		LOG("Bailing as this is not a regular file\n");
12880 		swd_flags |= SWD_FILEOP_ERROR;
12881 		goto exit;
12882 	}
12883 	VATTR_INIT(&va);
12884 	VATTR_SET(&va, va_data_size, 0);
12885 	vnode_setattr(vp, &va, ctx);
12886 
12887 
12888 	if (buf != NULL) {
12889 		error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12890 		    UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12891 		if (error != 0) {
12892 			LOG("Failed to save sleep wake log. err 0x%x\n", error);
12893 			swd_flags |= SWD_FILEOP_ERROR;
12894 		} else {
12895 			DLOG("Saved %d bytes to file %s\n", len, name);
12896 		}
12897 	}
12898 
12899 exit:
12900 	if (vp) {
12901 		vnode_close(vp, FWRITE, ctx);
12902 	}
12903 	if (ctx) {
12904 		vfs_context_rele(ctx);
12905 	}
12906 
12907 	return error;
12908 }
12909 
12910 #else /* defined(__i386__) || defined(__x86_64__) */
12911 
12912 void
12913 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12914 {
12915 	if (restart) {
12916 		if (gSwdPanic == 0) {
12917 			return;
12918 		}
12919 		panic("Sleep/Wake hang detected");
12920 		return;
12921 	}
12922 }
12923 
12924 void
12925 IOPMrootDomain::takeStackshot(bool restart)
12926 {
12927 #pragma unused(restart)
12928 }
12929 
12930 void
12931 IOPMrootDomain::deleteStackshot()
12932 {
12933 }
12934 
12935 void
12936 IOPMrootDomain::sleepWakeDebugMemAlloc()
12937 {
12938 }
12939 
12940 void
12941 IOPMrootDomain::saveFailureData2File()
12942 {
12943 }
12944 
12945 void
12946 IOPMrootDomain::sleepWakeDebugEnableWdog()
12947 {
12948 }
12949 
12950 bool
12951 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12952 {
12953 	return false;
12954 }
12955 
12956 void
12957 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12958 {
12959 }
12960 
12961 errno_t
12962 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12963 {
12964 	return 0;
12965 }
12966 
12967 #endif /* defined(__i386__) || defined(__x86_64__) */
12968 
12969