xref: /xnu-10063.121.3/iokit/Kernel/IOPMrootDomain.cpp (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
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 <console/video_console.h>
64 #include <sys/syslog.h>
65 #include <sys/sysctl.h>
66 #include <sys/vnode.h>
67 #include <sys/vnode_internal.h>
68 #include <sys/fcntl.h>
69 #include <os/log.h>
70 #include <pexpert/protos.h>
71 #include <AssertMacros.h>
72 
73 #include <sys/time.h>
74 #include "IOServicePrivate.h"   // _IOServiceInterestNotifier
75 #include "IOServicePMPrivate.h"
76 
77 #include <libkern/zlib.h>
78 #include <os/cpp_util.h>
79 #include <os/atomic_private.h>
80 #include <libkern/c++/OSBoundedArrayRef.h>
81 
82 #if DEVELOPMENT || DEBUG
83 #include <os/system_event_log.h>
84 #endif /* DEVELOPMENT || DEBUG */
85 
86 __BEGIN_DECLS
87 #include <mach/shared_region.h>
88 #include <kern/clock.h>
89 __END_DECLS
90 
91 #if defined(__i386__) || defined(__x86_64__)
92 __BEGIN_DECLS
93 #include "IOPMrootDomainInternal.h"
94 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
95 __END_DECLS
96 #endif
97 
98 #define kIOPMrootDomainClass    "IOPMrootDomain"
99 #define LOG_PREFIX              "PMRD: "
100 
101 
102 #define MSG(x...) \
103     do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
104 
105 #define LOG(x...)    \
106     do { kprintf(LOG_PREFIX x); } while (false)
107 
108 #if DEVELOPMENT || DEBUG
109 #define DEBUG_LOG(x...) do { \
110     if (kIOLogPMRootDomain & gIOKitDebug) \
111     kprintf(LOG_PREFIX x); \
112     os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
113 } while (false)
114 #else
115 #define DEBUG_LOG(x...)
116 #endif
117 
118 #define DLOG(x...)  do { \
119     if (kIOLogPMRootDomain & gIOKitDebug) \
120 	IOLog(LOG_PREFIX x); \
121     else \
122 	os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
123 } while (false)
124 
125 #define DMSG(x...)  do { \
126     if (kIOLogPMRootDomain & gIOKitDebug) { \
127 	kprintf(LOG_PREFIX x); \
128     } \
129 } while (false)
130 
131 
132 #define _LOG(x...)
133 
134 #define CHECK_THREAD_CONTEXT
135 #ifdef  CHECK_THREAD_CONTEXT
136 static IOWorkLoop * gIOPMWorkLoop = NULL;
137 #define ASSERT_GATED()                                      \
138 do {                                                        \
139     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
140 	panic("RootDomain: not inside PM gate");            \
141     }                                                       \
142 } while(false)
143 #else
144 #define ASSERT_GATED()
145 #endif /* CHECK_THREAD_CONTEXT */
146 
147 #define CAP_LOSS(c)  \
148 	(((_pendingCapability & (c)) == 0) && \
149 	 ((_currentCapability & (c)) != 0))
150 
151 #define CAP_GAIN(c)  \
152 	(((_currentCapability & (c)) == 0) && \
153 	 ((_pendingCapability & (c)) != 0))
154 
155 #define CAP_CHANGE(c)    \
156 	(((_currentCapability ^ _pendingCapability) & (c)) != 0)
157 
158 #define CAP_CURRENT(c)  \
159 	((_currentCapability & (c)) != 0)
160 
161 #define CAP_HIGHEST(c)  \
162 	((_highestCapability & (c)) != 0)
163 
164 #define CAP_PENDING(c)  \
165 	((_pendingCapability & (c)) != 0)
166 
167 // rdar://problem/9157444
168 #if defined(__i386__) || defined(__x86_64__)
169 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY   20
170 #endif
171 
172 // Event types for IOPMPowerStateQueue::submitPowerEvent()
173 enum {
174 	kPowerEventFeatureChanged = 1,             // 1
175 	kPowerEventReceivedPowerNotification,      // 2
176 	kPowerEventSystemBootCompleted,            // 3
177 	kPowerEventSystemShutdown,                 // 4
178 	kPowerEventUserDisabledSleep,              // 5
179 	kPowerEventRegisterSystemCapabilityClient, // 6
180 	kPowerEventRegisterKernelCapabilityClient, // 7
181 	kPowerEventPolicyStimulus,                 // 8
182 	kPowerEventAssertionCreate,                // 9
183 	kPowerEventAssertionRelease,               // 10
184 	kPowerEventAssertionSetLevel,              // 11
185 	kPowerEventQueueSleepWakeUUID,             // 12
186 	kPowerEventPublishSleepWakeUUID,           // 13
187 	kPowerEventSetDisplayPowerOn,              // 14
188 	kPowerEventPublishWakeType,                // 15
189 	kPowerEventAOTEvaluate                     // 16
190 };
191 
192 // For evaluatePolicy()
193 // List of stimuli that affects the root domain policy.
194 enum {
195 	kStimulusDisplayWranglerSleep,      // 0
196 	kStimulusDisplayWranglerWake,       // 1
197 	kStimulusAggressivenessChanged,     // 2
198 	kStimulusDemandSystemSleep,         // 3
199 	kStimulusAllowSystemSleepChanged,   // 4
200 	kStimulusDarkWakeActivityTickle,    // 5
201 	kStimulusDarkWakeEntry,             // 6
202 	kStimulusDarkWakeReentry,           // 7
203 	kStimulusDarkWakeEvaluate,          // 8
204 	kStimulusNoIdleSleepPreventers,     // 9
205 	kStimulusEnterUserActiveState,      // 10
206 	kStimulusLeaveUserActiveState       // 11
207 };
208 
209 // Internal power state change reasons
210 // Must be less than kIOPMSleepReasonClamshell=101
211 enum {
212 	kCPSReasonNone = 0,                 // 0
213 	kCPSReasonInit,                     // 1
214 	kCPSReasonWake,                     // 2
215 	kCPSReasonIdleSleepPrevent,         // 3
216 	kCPSReasonIdleSleepAllow,           // 4
217 	kCPSReasonPowerOverride,            // 5
218 	kCPSReasonPowerDownCancel,          // 6
219 	kCPSReasonAOTExit,                  // 7
220 	kCPSReasonAdjustPowerState,         // 8
221 	kCPSReasonDarkWakeCannotSleep,      // 9
222 	kCPSReasonIdleSleepEnabled,         // 10
223 	kCPSReasonEvaluatePolicy,           // 11
224 	kCPSReasonSustainFullWake,          // 12
225 	kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
226 };
227 
228 extern "C" {
229 IOReturn OSKextSystemSleepOrWake( UInt32 );
230 }
231 extern "C" ppnum_t      pmap_find_phys(pmap_t pmap, addr64_t va);
232 extern "C" addr64_t     kvtophys(vm_offset_t va);
233 extern "C" boolean_t    kdp_has_polled_corefile();
234 
235 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
236 static void notifySystemShutdown( IOService * root, uint32_t messageType );
237 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
238 static void pmEventTimeStamp(uint64_t *recordTS);
239 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
240 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
241 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
242 
243 static int  IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
244 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
245 #define YMDTF       "%04d/%02d/%d %02d:%02d:%02d"
246 #define YMDT(cal)   ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
247 
248 // "IOPMSetSleepSupported"  callPlatformFunction name
249 static OSSharedPtr<const OSSymbol>         sleepSupportedPEFunction;
250 static OSSharedPtr<const OSSymbol>         sleepMessagePEFunction;
251 static OSSharedPtr<const OSSymbol>         gIOPMWakeTypeUserKey;
252 
253 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalConnectedKey;
254 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalChargeCapableKey;
255 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryInstalledKey;
256 static OSSharedPtr<const OSSymbol>         gIOPMPSIsChargingKey;
257 static OSSharedPtr<const OSSymbol>         gIOPMPSAtWarnLevelKey;
258 static OSSharedPtr<const OSSymbol>         gIOPMPSAtCriticalLevelKey;
259 static OSSharedPtr<const OSSymbol>         gIOPMPSCurrentCapacityKey;
260 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxCapacityKey;
261 static OSSharedPtr<const OSSymbol>         gIOPMPSDesignCapacityKey;
262 static OSSharedPtr<const OSSymbol>         gIOPMPSTimeRemainingKey;
263 static OSSharedPtr<const OSSymbol>         gIOPMPSAmperageKey;
264 static OSSharedPtr<const OSSymbol>         gIOPMPSVoltageKey;
265 static OSSharedPtr<const OSSymbol>         gIOPMPSCycleCountKey;
266 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxErrKey;
267 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterInfoKey;
268 static OSSharedPtr<const OSSymbol>         gIOPMPSLocationKey;
269 static OSSharedPtr<const OSSymbol>         gIOPMPSErrorConditionKey;
270 static OSSharedPtr<const OSSymbol>         gIOPMPSManufacturerKey;
271 static OSSharedPtr<const OSSymbol>         gIOPMPSManufactureDateKey;
272 static OSSharedPtr<const OSSymbol>         gIOPMPSModelKey;
273 static OSSharedPtr<const OSSymbol>         gIOPMPSSerialKey;
274 static OSSharedPtr<const OSSymbol>         gIOPMPSLegacyBatteryInfoKey;
275 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryHealthKey;
276 static OSSharedPtr<const OSSymbol>         gIOPMPSHealthConfidenceKey;
277 static OSSharedPtr<const OSSymbol>         gIOPMPSCapacityEstimatedKey;
278 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryChargeStatusKey;
279 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryTemperatureKey;
280 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsKey;
281 static OSSharedPtr<const OSSymbol>         gIOPMPSChargerConfigurationKey;
282 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsIDKey;
283 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsWattsKey;
284 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsRevisionKey;
285 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSerialNumberKey;
286 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsFamilyKey;
287 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsAmperageKey;
288 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsDescriptionKey;
289 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsPMUConfigurationKey;
290 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSourceIDKey;
291 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsErrorFlagsKey;
292 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSharedSourceKey;
293 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsCloakedKey;
294 static OSSharedPtr<const OSSymbol>         gIOPMPSInvalidWakeSecondsKey;
295 static OSSharedPtr<const OSSymbol>         gIOPMPSPostChargeWaitSecondsKey;
296 static OSSharedPtr<const OSSymbol>         gIOPMPSPostDishargeWaitSecondsKey;
297 
298 #define kIOSleepSupportedKey        "IOSleepSupported"
299 #define kIOPMSystemCapabilitiesKey  "System Capabilities"
300 #define kIOPMSystemDefaultOverrideKey   "SystemPowerProfileOverrideDict"
301 
302 #define kIORequestWranglerIdleKey   "IORequestIdle"
303 #define kDefaultWranglerIdlePeriod  1000 // in milliseconds
304 
305 #define kIOSleepWakeFailureString   "SleepWakeFailureString"
306 #define kIOEFIBootRomFailureKey     "wake-failure"
307 #define kIOSleepWakeFailurePanic    "SleepWakeFailurePanic"
308 
309 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
310 	                   | kIOPMSupportedOnBatt \
311 	                   | kIOPMSupportedOnUPS)
312 
313 #define kLocalEvalClamshellCommand  (1 << 15)
314 #define kIdleSleepRetryInterval     (3 * 60 * 1000)
315 
316 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
317 // We impose this minimum to avoid race conditions in the AP wake path where
318 // userspace clients are not able to acquire power assertions before the idle timer expires.
319 #define kMinimumTimeBeforeIdleSleep     1000
320 
321 #define DISPLAY_WRANGLER_PRESENT    (!NO_KERNEL_HID)
322 
323 enum {
324 	kWranglerPowerStateMin   = 0,
325 	kWranglerPowerStateSleep = 2,
326 	kWranglerPowerStateDim   = 3,
327 	kWranglerPowerStateMax   = 4
328 };
329 
330 enum {
331 	OFF_STATE           = 0,
332 	RESTART_STATE       = 1,
333 	SLEEP_STATE         = 2,
334 	AOT_STATE           = 3,
335 	ON_STATE            = 4,
336 	NUM_POWER_STATES
337 };
338 
339 const char *
getPowerStateString(uint32_t state)340 getPowerStateString( uint32_t state )
341 {
342 #define POWER_STATE(x) {(uint32_t) x, #x}
343 
344 	static const IONamedValue powerStates[] = {
345 		POWER_STATE( OFF_STATE ),
346 		POWER_STATE( RESTART_STATE ),
347 		POWER_STATE( SLEEP_STATE ),
348 		POWER_STATE( AOT_STATE ),
349 		POWER_STATE( ON_STATE ),
350 		{ 0, NULL }
351 	};
352 	return IOFindNameForValue(state, powerStates);
353 }
354 
355 #define ON_POWER        kIOPMPowerOn
356 #define RESTART_POWER   kIOPMRestart
357 #define SLEEP_POWER     kIOPMAuxPowerOn
358 
359 static IOPMPowerState
360     ourPowerStates[NUM_POWER_STATES] =
361 {
362 	{   .version                = 1,
363 	    .capabilityFlags        = 0,
364 	    .outputPowerCharacter   = 0,
365 	    .inputPowerRequirement  = 0 },
366 	{   .version                = 1,
367 	    .capabilityFlags        = kIOPMRestartCapability,
368 	    .outputPowerCharacter   = kIOPMRestart,
369 	    .inputPowerRequirement  = RESTART_POWER },
370 	{   .version                = 1,
371 	    .capabilityFlags        = kIOPMSleepCapability,
372 	    .outputPowerCharacter   = kIOPMSleep,
373 	    .inputPowerRequirement  = SLEEP_POWER },
374 	{   .version                = 1,
375 	    .capabilityFlags        = kIOPMAOTCapability,
376 	    .outputPowerCharacter   = kIOPMAOTPower,
377 	    .inputPowerRequirement  = ON_POWER },
378 	{   .version                = 1,
379 	    .capabilityFlags        = kIOPMPowerOn,
380 	    .outputPowerCharacter   = kIOPMPowerOn,
381 	    .inputPowerRequirement  = ON_POWER },
382 };
383 
384 #define kIOPMRootDomainWakeTypeSleepService     "SleepService"
385 #define kIOPMRootDomainWakeTypeMaintenance      "Maintenance"
386 #define kIOPMRootDomainWakeTypeSleepTimer       "SleepTimer"
387 #define kIOPMrootDomainWakeTypeLowBattery       "LowBattery"
388 #define kIOPMRootDomainWakeTypeUser             "User"
389 #define kIOPMRootDomainWakeTypeAlarm            "Alarm"
390 #define kIOPMRootDomainWakeTypeNetwork          "Network"
391 #define kIOPMRootDomainWakeTypeHIDActivity      "HID Activity"
392 #define kIOPMRootDomainWakeTypeNotification     "Notification"
393 #define kIOPMRootDomainWakeTypeHibernateError   "HibernateError"
394 
395 // Special interest that entitles the interested client from receiving
396 // all system messages. Only used by powerd.
397 //
398 #define kIOPMSystemCapabilityInterest       "IOPMSystemCapabilityInterest"
399 
400 // Entitlement required for root domain clients
401 #define kRootDomainEntitlementSetProperty   "com.apple.private.iokit.rootdomain-set-property"
402 
403 #define WAKEEVENT_LOCK()        IOLockLock(wakeEventLock)
404 #define WAKEEVENT_UNLOCK()      IOLockUnlock(wakeEventLock)
405 
406 /*
407  * Aggressiveness
408  */
409 #define AGGRESSIVES_LOCK()      IOLockLock(featuresDictLock)
410 #define AGGRESSIVES_UNLOCK()    IOLockUnlock(featuresDictLock)
411 
412 #define kAggressivesMinValue    1
413 
414 const char *
getAggressivenessTypeString(uint32_t type)415 getAggressivenessTypeString( uint32_t type )
416 {
417 #define AGGRESSIVENESS_TYPE(x) {(uint32_t) x, #x}
418 
419 	static const IONamedValue aggressivenessTypes[] = {
420 		AGGRESSIVENESS_TYPE( kPMGeneralAggressiveness ),
421 		AGGRESSIVENESS_TYPE( kPMMinutesToDim ),
422 		AGGRESSIVENESS_TYPE( kPMMinutesToSpinDown ),
423 		AGGRESSIVENESS_TYPE( kPMMinutesToSleep ),
424 		AGGRESSIVENESS_TYPE( kPMEthernetWakeOnLANSettings ),
425 		AGGRESSIVENESS_TYPE( kPMSetProcessorSpeed ),
426 		AGGRESSIVENESS_TYPE( kPMPowerSource),
427 		AGGRESSIVENESS_TYPE( kPMMotionSensor ),
428 		AGGRESSIVENESS_TYPE( kPMLastAggressivenessType ),
429 		{ 0, NULL }
430 	};
431 	return IOFindNameForValue(type, aggressivenessTypes);
432 }
433 
434 enum {
435 	kAggressivesStateBusy           = 0x01,
436 	kAggressivesStateQuickSpindown  = 0x02
437 };
438 
439 struct AggressivesRecord {
440 	uint32_t    flags;
441 	uint32_t    type;
442 	uint32_t    value;
443 };
444 
445 struct AggressivesRequest {
446 	queue_chain_t           chain;
447 	uint32_t                options;
448 	uint32_t                dataType;
449 	union {
450 		OSSharedPtr<IOService> service;
451 		AggressivesRecord      record;
452 	} data;
453 };
454 
455 enum {
456 	kAggressivesRequestTypeService  = 1,
457 	kAggressivesRequestTypeRecord
458 };
459 
460 enum {
461 	kAggressivesOptionSynchronous          = 0x00000001,
462 	kAggressivesOptionQuickSpindownEnable  = 0x00000100,
463 	kAggressivesOptionQuickSpindownDisable = 0x00000200,
464 	kAggressivesOptionQuickSpindownMask    = 0x00000300
465 };
466 
467 enum {
468 	kAggressivesRecordFlagModified         = 0x00000001,
469 	kAggressivesRecordFlagMinValue         = 0x00000002
470 };
471 
472 // System Sleep Preventers
473 
474 enum {
475 	kPMUserDisabledAllSleep = 1,
476 	kPMSystemRestartBootingInProgress,
477 	kPMConfigPreventSystemSleep,
478 	kPMChildPreventSystemSleep,
479 	kPMCPUAssertion,
480 	kPMPCIUnsupported,
481 	kPMDKNotReady,
482 };
483 
484 const char *
getSystemSleepPreventerString(uint32_t preventer)485 getSystemSleepPreventerString( uint32_t preventer )
486 {
487 #define SYSTEM_SLEEP_PREVENTER(x) {(int) x, #x}
488 	static const IONamedValue systemSleepPreventers[] = {
489 		SYSTEM_SLEEP_PREVENTER( kPMUserDisabledAllSleep ),
490 		SYSTEM_SLEEP_PREVENTER( kPMSystemRestartBootingInProgress ),
491 		SYSTEM_SLEEP_PREVENTER( kPMConfigPreventSystemSleep ),
492 		SYSTEM_SLEEP_PREVENTER( kPMChildPreventSystemSleep ),
493 		SYSTEM_SLEEP_PREVENTER( kPMCPUAssertion ),
494 		SYSTEM_SLEEP_PREVENTER( kPMPCIUnsupported ),
495 		SYSTEM_SLEEP_PREVENTER( kPMDKNotReady ),
496 		{ 0, NULL }
497 	};
498 	return IOFindNameForValue(preventer, systemSleepPreventers);
499 }
500 
501 // gDarkWakeFlags
502 enum {
503 	kDarkWakeFlagPromotionNone       = 0x0000,
504 	kDarkWakeFlagPromotionEarly      = 0x0001, // promote before gfx clamp
505 	kDarkWakeFlagPromotionLate       = 0x0002, // promote after gfx clamp
506 	kDarkWakeFlagPromotionMask       = 0x0003,
507 	kDarkWakeFlagAlarmIsDark         = 0x0100,
508 	kDarkWakeFlagAudioNotSuppressed  = 0x0200,
509 	kDarkWakeFlagUserWakeWorkaround  = 0x1000
510 };
511 
512 // gClamshellFlags
513 // The workaround for 9157444 is enabled at compile time using the
514 // DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY macro and is not represented below.
515 enum {
516 	kClamshell_WAR_38378787 = 0x00000001,
517 	kClamshell_WAR_47715679 = 0x00000002,
518 	kClamshell_WAR_58009435 = 0x00000004
519 };
520 
521 // acceptSystemWakeEvents()
522 enum {
523 	kAcceptSystemWakeEvents_Disable = 0,
524 	kAcceptSystemWakeEvents_Enable,
525 	kAcceptSystemWakeEvents_Reenable
526 };
527 
528 static IOPMrootDomain * gRootDomain;
529 static IORootParent *   gPatriarch;
530 static IONotifier *     gSysPowerDownNotifier = NULL;
531 static UInt32           gSleepOrShutdownPending = 0;
532 static UInt32           gWillShutdown = 0;
533 static UInt32           gPagingOff = 0;
534 static UInt32           gSleepWakeUUIDIsSet = false;
535 static uint32_t         gAggressivesState = 0;
536 uint32_t                gHaltTimeMaxLog;
537 uint32_t                gHaltTimeMaxPanic;
538 IOLock *                gHaltLogLock;
539 static char *           gHaltLog;
540 enum                  { kHaltLogSize = 2048 };
541 static size_t           gHaltLogPos;
542 static uint64_t         gHaltStartTime;
543 static char             gKextNameBuf[64];
544 static size_t           gKextNamePos;
545 static bool             gKextNameEnd;
546 
547 uuid_string_t bootsessionuuid_string;
548 
549 #if defined(XNU_TARGET_OS_OSX)
550 #if DISPLAY_WRANGLER_PRESENT
551 static uint32_t         gDarkWakeFlags = kDarkWakeFlagPromotionNone;
552 #elif defined(__arm64__)
553 // Enable temporary full wake promotion workarounds
554 static uint32_t         gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
555 #else
556 // Enable full wake promotion workarounds
557 static uint32_t         gDarkWakeFlags = kDarkWakeFlagUserWakeWorkaround;
558 #endif
559 #else  /* !defined(XNU_TARGET_OS_OSX) */
560 static uint32_t         gDarkWakeFlags = kDarkWakeFlagPromotionEarly;
561 #endif /* !defined(XNU_TARGET_OS_OSX) */
562 
563 static uint32_t         gNoIdleFlag = 0;
564 static uint32_t         gSleepDisabledFlag = 0;
565 static uint32_t         gSwdPanic = 1;
566 static uint32_t         gSwdSleepTimeout = 0;
567 static uint32_t         gSwdWakeTimeout = 0;
568 static uint32_t         gSwdSleepWakeTimeout = 0;
569 static PMStatsStruct    gPMStats;
570 #if DEVELOPMENT || DEBUG
571 static uint32_t swd_panic_phase;
572 #endif
573 
574 static uint32_t         gClamshellFlags = 0
575 #if defined(__i386__) || defined(__x86_64__)
576     | kClamshell_WAR_58009435
577 #endif
578 ;
579 
580 #if HIBERNATION
581 
582 #if defined(__arm64__)
583 static IOReturn
defaultSleepPolicyHandler(void * ctx,const IOPMSystemSleepPolicyVariables * vars,IOPMSystemSleepParameters * params)584 defaultSleepPolicyHandler(void *ctx, const IOPMSystemSleepPolicyVariables *vars, IOPMSystemSleepParameters *params)
585 {
586 	uint32_t sleepType = kIOPMSleepTypeDeepIdle;
587 
588 	assert(vars->signature == kIOPMSystemSleepPolicySignature);
589 	assert(vars->version == kIOPMSystemSleepPolicyVersion);
590 
591 	// Hibernation enabled and either user forced hibernate or low battery sleep
592 	if ((vars->hibernateMode & kIOHibernateModeOn) &&
593 	    (((vars->hibernateMode & kIOHibernateModeSleep) == 0) ||
594 	    (vars->sleepFactors & kIOPMSleepFactorBatteryLow))) {
595 		sleepType = kIOPMSleepTypeHibernate;
596 	}
597 	params->version = kIOPMSystemSleepParametersVersion;
598 	params->sleepType = sleepType;
599 	return kIOReturnSuccess;
600 }
601 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = &defaultSleepPolicyHandler;
602 #else /* defined(__arm64__) */
603 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = NULL;
604 #endif /* defined(__arm64__) */
605 
606 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = NULL;
607 static void *                           gSleepPolicyTarget;
608 #endif
609 
610 struct timeval gIOLastSleepTime;
611 struct timeval gIOLastWakeTime;
612 AbsoluteTime gIOLastWakeAbsTime;
613 AbsoluteTime gIOLastSleepAbsTime;
614 
615 struct timeval gIOLastUserSleepTime;
616 
617 static char gWakeReasonString[128];
618 static char gBootReasonString[80];
619 static char gShutdownReasonString[80];
620 static bool gWakeReasonSysctlRegistered = false;
621 static bool gBootReasonSysctlRegistered = false;
622 static bool gShutdownReasonSysctlRegistered = false;
623 static bool gWillShutdownSysctlRegistered = false;
624 static AbsoluteTime gUserActiveAbsTime;
625 static AbsoluteTime gUserInactiveAbsTime;
626 
627 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
628 static bool gSpinDumpBufferFull = false;
629 #endif
630 
631 z_stream          swd_zs;
632 vm_offset_t swd_zs_zmem;
633 //size_t swd_zs_zsize;
634 size_t swd_zs_zoffset;
635 #if defined(__i386__) || defined(__x86_64__)
636 IOCPU *currentShutdownTarget = NULL;
637 #endif
638 
639 static unsigned int     gPMHaltBusyCount;
640 static unsigned int     gPMHaltIdleCount;
641 static int              gPMHaltDepth;
642 static uint32_t         gPMHaltMessageType;
643 static IOLock *         gPMHaltLock  = NULL;
644 static OSSharedPtr<OSArray>        gPMHaltArray;
645 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
646 static bool             gPMQuiesced;
647 
648 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
649 #define kCPUUnknownIndex    9999999
650 enum {
651 	kInformAC = 0,
652 	kInformLid = 1,
653 	kInformableCount = 2
654 };
655 
656 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
657 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
658 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
659 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
660 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
661 
662 #define kBadPMFeatureID     0
663 
664 /*
665  * PMSettingHandle
666  * Opaque handle passed to clients of registerPMSettingController()
667  */
668 class PMSettingHandle : public OSObject
669 {
670 	OSDeclareFinalStructors( PMSettingHandle );
671 	friend class PMSettingObject;
672 
673 private:
674 	PMSettingObject *pmso;
675 	void free(void) APPLE_KEXT_OVERRIDE;
676 };
677 
678 /*
679  * PMSettingObject
680  * Internal object to track each PM setting controller
681  */
682 class PMSettingObject : public OSObject
683 {
684 	OSDeclareFinalStructors( PMSettingObject );
685 	friend class IOPMrootDomain;
686 
687 private:
688 	queue_head_t                    calloutQueue;
689 	thread_t                        waitThread;
690 	IOPMrootDomain                  *parent;
691 	PMSettingHandle                 *pmsh;
692 	IOPMSettingControllerCallback   func;
693 	OSObject                        *target;
694 	uintptr_t                       refcon;
695 	OSDataAllocation<uint32_t>      publishedFeatureID;
696 	uint32_t                        settingCount;
697 	bool                            disabled;
698 
699 	void free(void) APPLE_KEXT_OVERRIDE;
700 
701 public:
702 	static PMSettingObject *pmSettingObject(
703 		IOPMrootDomain                  *parent_arg,
704 		IOPMSettingControllerCallback   handler_arg,
705 		OSObject                        *target_arg,
706 		uintptr_t                       refcon_arg,
707 		uint32_t                        supportedPowerSources,
708 		const OSSymbol                  *settings[],
709 		OSObject                        **handle_obj);
710 
711 	IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
712 	void clientHandleFreed(void);
713 };
714 
715 struct PMSettingCallEntry {
716 	queue_chain_t   link;
717 	thread_t        thread;
718 };
719 
720 #define PMSETTING_LOCK()    IOLockLock(settingsCtrlLock)
721 #define PMSETTING_UNLOCK()  IOLockUnlock(settingsCtrlLock)
722 #define PMSETTING_WAIT(p)   IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
723 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
724 
725 /*
726  * PMTraceWorker
727  * Internal helper object for logging trace points to RTC
728  * IOPMrootDomain and only IOPMrootDomain should instantiate
729  * exactly one of these.
730  */
731 
732 typedef void (*IOPMTracePointHandler)(
733 	void * target, uint32_t code, uint32_t data );
734 
735 class PMTraceWorker : public OSObject
736 {
737 	OSDeclareDefaultStructors(PMTraceWorker);
738 public:
739 	typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
740 
741 	static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
742 	void                        tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
743 	void                        tracePoint(uint8_t phase);
744 	void                        traceDetail(uint32_t detail);
745 	void                        traceComponentWakeProgress(uint32_t component, uint32_t data);
746 	int                         recordTopLevelPCIDevice(IOService *);
747 	void                        RTC_TRACE(void);
748 	virtual bool                serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
749 
750 	IOPMTracePointHandler       tracePointHandler;
751 	void *                      tracePointTarget;
752 	uint64_t                    getPMStatusCode();
753 	uint8_t                     getTracePhase();
754 	uint32_t                    getTraceData();
755 private:
756 	IOPMrootDomain              *owner;
757 	IOLock                      *pmTraceWorkerLock;
758 	OSSharedPtr<OSArray>         pciDeviceBitMappings;
759 
760 	uint8_t                     addedToRegistry;
761 	uint8_t                     tracePhase;
762 	uint32_t                    traceData32;
763 	uint8_t                     loginWindowData;
764 	uint8_t                     coreDisplayData;
765 	uint8_t                     coreGraphicsData;
766 };
767 
768 /*
769  * this should be treated as POD, as it's byte-copied around
770  * and we cannot rely on d'tor firing at the right time
771  */
772 struct PMAssertStruct {
773 	IOPMDriverAssertionID       id;
774 	IOPMDriverAssertionType     assertionBits;
775 	uint64_t                    createdTime;
776 	uint64_t                    modifiedTime;
777 	const OSSymbol              *ownerString;
778 	IOService                   *ownerService;
779 	uint64_t                    registryEntryID;
780 	IOPMDriverAssertionLevel    level;
781 	uint64_t                    assertCPUStartTime;
782 	uint64_t                    assertCPUDuration;
783 };
784 OSDefineValueObjectForDependentType(PMAssertStruct)
785 
786 /*
787  * PMAssertionsTracker
788  * Tracks kernel and user space PM assertions
789  */
790 class PMAssertionsTracker : public OSObject
791 {
792 	OSDeclareFinalStructors(PMAssertionsTracker);
793 public:
794 	static PMAssertionsTracker  *pmAssertionsTracker( IOPMrootDomain * );
795 
796 	IOReturn                    createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
797 	IOReturn                    releaseAssertion(IOPMDriverAssertionID);
798 	IOReturn                    setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
799 	IOReturn                    setUserAssertionLevels(IOPMDriverAssertionType);
800 
801 	OSSharedPtr<OSArray>        copyAssertionsArray(void);
802 	IOPMDriverAssertionType     getActivatedAssertions(void);
803 	IOPMDriverAssertionLevel    getAssertionLevel(IOPMDriverAssertionType);
804 
805 	IOReturn                    handleCreateAssertion(OSValueObject<PMAssertStruct> *);
806 	IOReturn                    handleReleaseAssertion(IOPMDriverAssertionID);
807 	IOReturn                    handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
808 	IOReturn                    handleSetUserAssertionLevels(void * arg0);
809 	void                        publishProperties(void);
810 	void                        reportCPUBitAccounting(void);
811 	PMAssertStruct              *detailsForID(IOPMDriverAssertionID, int *);
812 
813 private:
814 	uint32_t                    tabulateProducerCount;
815 	uint32_t                    tabulateConsumerCount;
816 
817 	uint64_t                    maxAssertCPUDuration;
818 	uint64_t                    maxAssertCPUEntryId;
819 
820 	void                        tabulate(void);
821 	void                        updateCPUBitAccounting(PMAssertStruct * assertStruct);
822 
823 	IOPMrootDomain              *owner;
824 	OSSharedPtr<OSArray>        assertionsArray;
825 	IOLock                      *assertionsArrayLock;
826 	IOPMDriverAssertionID       issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
827 	IOPMDriverAssertionType     assertionsKernel;
828 	IOPMDriverAssertionType     assertionsUser;
829 	IOPMDriverAssertionType     assertionsCombined;
830 };
831 
832 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
833 
834 /*
835  * PMHaltWorker
836  * Internal helper object for Shutdown/Restart notifications.
837  */
838 #define kPMHaltMaxWorkers   8
839 #define kPMHaltTimeoutMS    100
840 
841 class PMHaltWorker : public OSObject
842 {
843 	OSDeclareFinalStructors( PMHaltWorker );
844 
845 public:
846 	IOService *  service;// service being worked on
847 	AbsoluteTime startTime; // time when work started
848 	int          depth;  // work on nubs at this PM-tree depth
849 	int          visits; // number of nodes visited (debug)
850 	IOLock *     lock;
851 	bool         timeout;// service took too long
852 
853 	static  PMHaltWorker * worker( void );
854 	static  void main( void * arg, wait_result_t waitResult );
855 	static  void work( PMHaltWorker * me );
856 	static  void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
857 	virtual void free( void ) APPLE_KEXT_OVERRIDE;
858 };
859 
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)860 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
861 
862 
863 #define super IOService
864 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
865 
866 boolean_t
867 IOPMRootDomainGetWillShutdown(void)
868 {
869 	return gWillShutdown != 0;
870 }
871 
872 static void
IOPMRootDomainWillShutdown(void)873 IOPMRootDomainWillShutdown(void)
874 {
875 	if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
876 		IOService::willShutdown();
877 		for (int i = 0; i < 100; i++) {
878 			if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
879 				break;
880 			}
881 			IOSleep( 100 );
882 		}
883 	}
884 }
885 
886 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)887 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
888 {
889 	return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
890 }
891 
892 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)893 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
894 {
895 	return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
896 }
897 
898 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)899 acknowledgeSleepWakeNotification(void * PMrefcon)
900 {
901 	return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
902 }
903 
904 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)905 vetoSleepWakeNotification(void * PMrefcon)
906 {
907 	return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
908 }
909 
910 extern "C" IOReturn
rootDomainRestart(void)911 rootDomainRestart( void )
912 {
913 	return gRootDomain->restartSystem();
914 }
915 
916 extern "C" IOReturn
rootDomainShutdown(void)917 rootDomainShutdown( void )
918 {
919 	return gRootDomain->shutdownSystem();
920 }
921 
922 static void
halt_log_putc(char c)923 halt_log_putc(char c)
924 {
925 	if (gHaltLogPos >= (kHaltLogSize - 2)) {
926 		return;
927 	}
928 	gHaltLog[gHaltLogPos++] = c;
929 }
930 
931 extern "C" void
932 _doprnt_log(const char     *fmt,
933     va_list                 *argp,
934     void                    (*putc)(char),
935     int                     radix);
936 
937 static int
halt_log(const char * fmt,...)938 halt_log(const char *fmt, ...)
939 {
940 	va_list listp;
941 
942 	va_start(listp, fmt);
943 	_doprnt_log(fmt, &listp, &halt_log_putc, 16);
944 	va_end(listp);
945 
946 	return 0;
947 }
948 
949 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)950 halt_log_enter(const char * what, const void * pc, uint64_t time)
951 {
952 	uint64_t nano, millis;
953 
954 	if (!gHaltLog) {
955 		return;
956 	}
957 	absolutetime_to_nanoseconds(time, &nano);
958 	millis = nano / NSEC_PER_MSEC;
959 	if (millis < 100) {
960 		return;
961 	}
962 
963 	IOLockLock(gHaltLogLock);
964 	if (pc) {
965 		halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
966 		OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
967 		    OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
968 	} else {
969 		halt_log("%s: %qd ms\n", what, millis);
970 	}
971 
972 	gHaltLog[gHaltLogPos] = 0;
973 	IOLockUnlock(gHaltLogLock);
974 }
975 
976 extern  uint32_t                           gFSState;
977 
978 extern "C" void
IOSystemShutdownNotification(int howto,int stage)979 IOSystemShutdownNotification(int howto, int stage)
980 {
981 	uint64_t startTime;
982 
983 	if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
984 #if defined(XNU_TARGET_OS_OSX)
985 		uint64_t nano, millis;
986 		startTime = mach_absolute_time();
987 		IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
988 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
989 		millis = nano / NSEC_PER_MSEC;
990 		if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
991 			printf("waitQuiet() for unmount %qd ms\n", millis);
992 		}
993 #endif /* defined(XNU_TARGET_OS_OSX) */
994 		return;
995 	}
996 
997 	if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
998 		uint64_t nano, millis;
999 		startTime = mach_absolute_time();
1000 		IOServicePH::systemHalt(howto);
1001 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1002 		millis = nano / NSEC_PER_MSEC;
1003 		if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1004 			printf("IOServicePH::systemHalt took %qd ms\n", millis);
1005 		}
1006 		return;
1007 	}
1008 
1009 	assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1010 
1011 	IOLockLock(gHaltLogLock);
1012 	if (!gHaltLog) {
1013 		gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1014 		gHaltStartTime = mach_absolute_time();
1015 		if (gHaltLog) {
1016 			halt_log_putc('\n');
1017 		}
1018 	}
1019 	IOLockUnlock(gHaltLogLock);
1020 
1021 	startTime = mach_absolute_time();
1022 	IOPMRootDomainWillShutdown();
1023 	halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1024 #if HIBERNATION
1025 	startTime = mach_absolute_time();
1026 	IOHibernateSystemPostWake(true);
1027 	halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1028 #endif
1029 	if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1030 		gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1031 	}
1032 }
1033 
1034 extern "C" int sync_internal(void);
1035 
1036 /*
1037  *  A device is always in the highest power state which satisfies its driver,
1038  *  its policy-maker, and any power children it has, but within the constraint
1039  *  of the power state provided by its parent.  The driver expresses its desire by
1040  *  calling changePowerStateTo(), the policy-maker expresses its desire by calling
1041  *  changePowerStateToPriv(), and the children express their desires by calling
1042  *  requestPowerDomainState().
1043  *
1044  *  The Root Power Domain owns the policy for idle and demand sleep for the system.
1045  *  It is a power-managed IOService just like the others in the system.
1046  *  It implements several power states which map to what we see as Sleep and On.
1047  *
1048  *  The sleep policy is as follows:
1049  *  1. Sleep is prevented if the case is open so that nobody will think the machine
1050  *  is off and plug/unplug cards.
1051  *  2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1052  *  3. System cannot Sleep if some object in the tree is in a power state marked
1053  *  kIOPMPreventSystemSleep.
1054  *
1055  *  These three conditions are enforced using the "driver clamp" by calling
1056  *  changePowerStateTo(). For example, if the case is opened,
1057  *  changePowerStateTo(ON_STATE) is called to hold the system on regardless
1058  *  of the desires of the children of the root or the state of the other clamp.
1059  *
1060  *  Demand Sleep is initiated by pressing the front panel power button, closing
1061  *  the clamshell, or selecting the menu item. In this case the root's parent
1062  *  actually initiates the power state change so that the root domain has no
1063  *  choice and does not give applications the opportunity to veto the change.
1064  *
1065  *  Idle Sleep occurs if no objects in the tree are in a state marked
1066  *  kIOPMPreventIdleSleep.  When this is true, the root's children are not holding
1067  *  the root on, so it sets the "policy-maker clamp" by calling
1068  *  changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1069  *  This timer is set for the difference between the sleep timeout slider and the
1070  *  display dim timeout slider. When the timer expires, it releases its clamp and
1071  *  now nothing is holding it awake, so it falls asleep.
1072  *
1073  *  Demand sleep is prevented when the system is booting.  When preferences are
1074  *  transmitted by the loginwindow at the end of boot, a flag is cleared,
1075  *  and this allows subsequent Demand Sleep.
1076  */
1077 
1078 //******************************************************************************
1079 
1080 IOPMrootDomain *
construct(void)1081 IOPMrootDomain::construct( void )
1082 {
1083 	IOPMrootDomain  *root;
1084 
1085 	root = new IOPMrootDomain;
1086 	if (root) {
1087 		root->init();
1088 	}
1089 
1090 	return root;
1091 }
1092 
1093 //******************************************************************************
1094 // updateConsoleUsersCallout
1095 //
1096 //******************************************************************************
1097 
1098 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1099 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1100 {
1101 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1102 	rootDomain->updateConsoleUsers();
1103 }
1104 
1105 void
updateConsoleUsers(void)1106 IOPMrootDomain::updateConsoleUsers(void)
1107 {
1108 	IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1109 	updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1110 }
1111 
1112 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1113 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1114 {
1115 	bool newSuspend;
1116 
1117 	WAKEEVENT_LOCK();
1118 	if (newTasksSuspended != kTasksSuspendNoChange) {
1119 		tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1120 	}
1121 	if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1122 		_aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1123 	}
1124 	newSuspend = (tasksSuspended || _aotTasksSuspended);
1125 	if (newSuspend == tasksSuspendState) {
1126 		WAKEEVENT_UNLOCK();
1127 		return false;
1128 	}
1129 	tasksSuspendState = newSuspend;
1130 	WAKEEVENT_UNLOCK();
1131 	tasks_system_suspend(newSuspend);
1132 	return true;
1133 }
1134 
1135 //******************************************************************************
1136 
1137 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1138 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1139 {
1140 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1141 	uint32_t    notifyRef  = (uint32_t)(uintptr_t) p1;
1142 	uint32_t    powerState = rootDomain->getPowerState();
1143 
1144 	DLOG("disk_sync_callout ps=%u\n", powerState);
1145 
1146 	if (ON_STATE == powerState) {
1147 		sync_internal();
1148 
1149 #if HIBERNATION
1150 		// Block sleep until trim issued on previous wake path is completed.
1151 		IOHibernateSystemPostWake(true);
1152 #endif
1153 	}
1154 #if HIBERNATION
1155 	else {
1156 		IOHibernateSystemPostWake(false);
1157 
1158 		rootDomain->sleepWakeDebugSaveSpinDumpFile();
1159 	}
1160 #endif
1161 
1162 	rootDomain->allowPowerChange(notifyRef);
1163 	DLOG("disk_sync_callout finish\n");
1164 }
1165 
1166 //******************************************************************************
1167 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1168 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1169 {
1170 	AbsoluteTime    endTime;
1171 	UInt64          nano = 0;
1172 
1173 	clock_get_uptime(&endTime);
1174 	if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1175 		*elapsedTime = 0;
1176 	} else {
1177 		SUB_ABSOLUTETIME(&endTime, startTime);
1178 		absolutetime_to_nanoseconds(endTime, &nano);
1179 		*elapsedTime = endTime;
1180 	}
1181 
1182 	return (UInt32)(nano / NSEC_PER_MSEC);
1183 }
1184 
1185 //******************************************************************************
1186 
1187 static int
1188 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1189 {
1190 	struct timeval *swt = (struct timeval *)arg1;
1191 	struct proc *p = req->p;
1192 
1193 	if (p == kernproc) {
1194 		return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1195 	} else if (proc_is64bit(p)) {
1196 		struct user64_timeval t = {};
1197 		t.tv_sec = swt->tv_sec;
1198 		t.tv_usec = swt->tv_usec;
1199 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1200 	} else {
1201 		struct user32_timeval t = {};
1202 		t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1203 		t.tv_usec = swt->tv_usec;
1204 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1205 	}
1206 }
1207 
1208 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1209     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1210     &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1211 
1212 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1213     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1214     &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1215 
1216 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1217 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1218 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1219 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1220 
1221 static int
1222 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1223 {
1224 	int new_value, changed, error;
1225 
1226 	if (!gWillShutdownSysctlRegistered) {
1227 		return ENOENT;
1228 	}
1229 
1230 	error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1231 	if (changed) {
1232 		if (!gWillShutdown && (new_value == 1)) {
1233 			IOPMRootDomainWillShutdown();
1234 		} else {
1235 			error = EINVAL;
1236 		}
1237 	}
1238 	return error;
1239 }
1240 
1241 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1242     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1243     NULL, 0, sysctl_willshutdown, "I", "");
1244 
1245 #if defined(XNU_TARGET_OS_OSX)
1246 
1247 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1248 sysctl_progressmeterenable
1249 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1250 {
1251 	int error;
1252 	int new_value, changed;
1253 
1254 	error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1255 
1256 	if (changed) {
1257 		vc_enable_progressmeter(new_value);
1258 	}
1259 
1260 	return error;
1261 }
1262 
1263 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1264 sysctl_progressmeter
1265 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1266 {
1267 	int error;
1268 	int new_value, changed;
1269 
1270 	error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1271 
1272 	if (changed) {
1273 		vc_set_progressmeter(new_value);
1274 	}
1275 
1276 	return error;
1277 }
1278 
1279 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1280     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1281     NULL, 0, sysctl_progressmeterenable, "I", "");
1282 
1283 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1284     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1285     NULL, 0, sysctl_progressmeter, "I", "");
1286 
1287 #endif /* defined(XNU_TARGET_OS_OSX) */
1288 
1289 
1290 
1291 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1292 sysctl_consoleoptions
1293 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1294 {
1295 	int error, changed;
1296 	uint32_t new_value;
1297 
1298 	error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1299 
1300 	if (changed) {
1301 		vc_user_options.options = new_value;
1302 	}
1303 
1304 	return error;
1305 }
1306 
1307 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1308     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1309     NULL, 0, sysctl_consoleoptions, "I", "");
1310 
1311 
1312 static int
1313 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1314 {
1315 	return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1316 }
1317 
1318 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1319     CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1320     NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1321 
1322 
1323 static int
1324 sysctl_wakereason SYSCTL_HANDLER_ARGS
1325 {
1326 	char wr[sizeof(gWakeReasonString)];
1327 
1328 	wr[0] = '\0';
1329 	if (gRootDomain && gWakeReasonSysctlRegistered) {
1330 		gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1331 	} else {
1332 		return ENOENT;
1333 	}
1334 
1335 	return sysctl_io_string(req, wr, 0, 0, NULL);
1336 }
1337 
1338 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1339     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1340     NULL, 0, sysctl_wakereason, "A", "wakereason");
1341 
1342 static int
1343 sysctl_bootreason SYSCTL_HANDLER_ARGS
1344 {
1345 	if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1346 		return ENOENT;
1347 	}
1348 
1349 	return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1350 }
1351 
1352 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1353     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1354     NULL, 0, sysctl_bootreason, "A", "");
1355 
1356 static int
1357 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1358 {
1359 	char sr[sizeof(gShutdownReasonString)];
1360 
1361 	sr[0] = '\0';
1362 	if (gRootDomain && gShutdownReasonSysctlRegistered) {
1363 		gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1364 	} else {
1365 		return ENOENT;
1366 	}
1367 
1368 	return sysctl_io_string(req, sr, 0, 0, NULL);
1369 }
1370 
1371 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1372     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1373     NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1374 
1375 static int
1376 sysctl_targettype SYSCTL_HANDLER_ARGS
1377 {
1378 	IOService * root;
1379 	OSSharedPtr<OSObject>  obj;
1380 	OSData *    data;
1381 	char        tt[32];
1382 
1383 	tt[0] = '\0';
1384 	root = IOService::getServiceRoot();
1385 	if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1386 		if ((data = OSDynamicCast(OSData, obj.get()))) {
1387 			strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1388 		}
1389 	}
1390 	return sysctl_io_string(req, tt, 0, 0, NULL);
1391 }
1392 
1393 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1394     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1395     NULL, 0, sysctl_targettype, "A", "targettype");
1396 
1397 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1398 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1399 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1400 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1401 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1402 #if DEVELOPMENT || DEBUG
1403 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1404 #if defined(XNU_TARGET_OS_OSX)
1405 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1406 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1407 #endif /* defined(XNU_TARGET_OS_OSX) */
1408 #endif /* DEVELOPMENT || DEBUG */
1409 
1410 //******************************************************************************
1411 // AOT
1412 
1413 static int
1414 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1415 {
1416 	if (NULL == gRootDomain) {
1417 		return ENOENT;
1418 	}
1419 	if (NULL == gRootDomain->_aotMetrics) {
1420 		IOPMAOTMetrics nullMetrics = {};
1421 		return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1422 	}
1423 	return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1424 }
1425 
1426 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1427     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1428     NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1429 
1430 
1431 static int
update_aotmode(uint32_t mode)1432 update_aotmode(uint32_t mode)
1433 {
1434 	int result;
1435 
1436 	if (!gIOPMWorkLoop) {
1437 		return ENOENT;
1438 	}
1439 	result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1440 		unsigned int oldCount;
1441 
1442 		if (mode && !gRootDomain->_aotMetrics) {
1443 		        gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1444 		}
1445 
1446 		oldCount = gRootDomain->idleSleepPreventersCount();
1447 		gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1448 		gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1449 		return 0;
1450 	});
1451 	return result;
1452 }
1453 
1454 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1455 sysctl_aotmodebits
1456 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1457 {
1458 	int error, changed;
1459 	uint32_t new_value;
1460 
1461 	if (NULL == gRootDomain) {
1462 		return ENOENT;
1463 	}
1464 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1465 	if (changed && gIOPMWorkLoop) {
1466 		error = update_aotmode(new_value);
1467 	}
1468 
1469 	return error;
1470 }
1471 
1472 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1473     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1474     NULL, 0, sysctl_aotmodebits, "I", "");
1475 
1476 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1477 sysctl_aotmode
1478 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1479 {
1480 	int error, changed;
1481 	uint32_t new_value;
1482 
1483 	if (NULL == gRootDomain) {
1484 		return ENOENT;
1485 	}
1486 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1487 	if (changed && gIOPMWorkLoop) {
1488 		if (new_value) {
1489 			new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1490 		}
1491 		error = update_aotmode(new_value);
1492 	}
1493 
1494 	return error;
1495 }
1496 
1497 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1498     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1499     NULL, 0, sysctl_aotmode, "I", "");
1500 
1501 //******************************************************************************
1502 
1503 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1504 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1505 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1506 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1507 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1508 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1509 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1510 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1511 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1512 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1513 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1514 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1515 
1516 //******************************************************************************
1517 // start
1518 //
1519 //******************************************************************************
1520 
1521 #define kRootDomainSettingsCount           20
1522 #define kRootDomainNoPublishSettingsCount  4
1523 
1524 bool
start(IOService * nub)1525 IOPMrootDomain::start( IOService * nub )
1526 {
1527 	OSSharedPtr<OSIterator>      psIterator;
1528 	OSSharedPtr<OSDictionary>    tmpDict;
1529 
1530 	super::start(nub);
1531 
1532 	gRootDomain = this;
1533 	gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1534 	gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1535 	gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1536 	gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1537 	gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1538 	gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1539 	gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1540 	gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1541 	gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1542 	gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1543 	gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1544 	gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1545 
1546 	gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1547 	gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1548 	gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1549 	gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1550 	gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1551 
1552 	sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1553 	sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1554 	gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1555 
1556 	OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1557 	{
1558 		OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1559 		gIOPMSettingAutoWakeSecondsKey,
1560 		gIOPMSettingAutoPowerSecondsKey,
1561 		gIOPMSettingAutoWakeCalendarKey,
1562 		gIOPMSettingAutoPowerCalendarKey,
1563 		gIOPMSettingDebugWakeRelativeKey,
1564 		gIOPMSettingDebugPowerRelativeKey,
1565 		OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1566 		OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1567 		OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1568 		OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1569 		OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1570 		OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1571 		OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1572 		OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1573 		OSSymbol::withCString(kIOPMStateConsoleShutdown),
1574 		OSSymbol::withCString(kIOPMSettingProModeControl),
1575 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1576 		gIOPMSettingSilentRunningKey,
1577 		gIOPMSettingLowLatencyAudioModeKey,
1578 	};
1579 
1580 	OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1581 	{
1582 		OSSymbol::withCString(kIOPMSettingProModeControl),
1583 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1584 		gIOPMSettingSilentRunningKey,
1585 		gIOPMSettingLowLatencyAudioModeKey,
1586 	};
1587 
1588 #if DEVELOPMENT || DEBUG
1589 #if defined(XNU_TARGET_OS_OSX)
1590 	PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1591 	PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1592 #endif /* defined(XNU_TARGET_OS_OSX) */
1593 #endif /* DEVELOPMENT || DEBUG */
1594 
1595 	PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1596 	PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1597 	PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1598 	PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1599 	PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1600 	PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1601 
1602 	// read noidle setting from Device Tree
1603 	if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1604 		DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1605 	}
1606 
1607 	queue_init(&aggressivesQueue);
1608 	aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1609 	aggressivesData = OSData::withCapacity(
1610 		sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1611 
1612 	featuresDictLock = IOLockAlloc();
1613 	settingsCtrlLock = IOLockAlloc();
1614 	wakeEventLock = IOLockAlloc();
1615 	gHaltLogLock = IOLockAlloc();
1616 	setPMRootDomain(this);
1617 
1618 	extraSleepTimer = thread_call_allocate(
1619 		idleSleepTimerExpired,
1620 		(thread_call_param_t) this);
1621 
1622 	powerButtonDown = thread_call_allocate(
1623 		powerButtonDownCallout,
1624 		(thread_call_param_t) this);
1625 
1626 	powerButtonUp = thread_call_allocate(
1627 		powerButtonUpCallout,
1628 		(thread_call_param_t) this);
1629 
1630 	diskSyncCalloutEntry = thread_call_allocate(
1631 		&disk_sync_callout,
1632 		(thread_call_param_t) this);
1633 	updateConsoleUsersEntry = thread_call_allocate(
1634 		&updateConsoleUsersCallout,
1635 		(thread_call_param_t) this);
1636 
1637 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1638 	fullWakeThreadCall = thread_call_allocate_with_options(
1639 		OSMemberFunctionCast(thread_call_func_t, this,
1640 		&IOPMrootDomain::fullWakeDelayedWork),
1641 		(thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1642 		THREAD_CALL_OPTIONS_ONCE);
1643 #endif
1644 
1645 	setProperty(kIOSleepSupportedKey, true);
1646 
1647 	bzero(&gPMStats, sizeof(gPMStats));
1648 
1649 	pmTracer = PMTraceWorker::tracer(this);
1650 
1651 	pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1652 
1653 	userDisabledAllSleep = false;
1654 	systemBooting = true;
1655 	idleSleepEnabled = false;
1656 	sleepSlider = 0;
1657 	idleSleepTimerPending = false;
1658 	wrangler = NULL;
1659 	clamshellClosed = false;
1660 	clamshellExists = false;
1661 #if DISPLAY_WRANGLER_PRESENT
1662 	clamshellDisabled = true;
1663 #else
1664 	clamshellDisabled = false;
1665 #endif
1666 	clamshellIgnoreClose = false;
1667 	acAdaptorConnected = true;
1668 	clamshellSleepDisableMask = 0;
1669 	gWakeReasonString[0] = '\0';
1670 
1671 	// Initialize to user active.
1672 	// Will never transition to user inactive w/o wrangler.
1673 	fullWakeReason = kFullWakeReasonLocalUser;
1674 	userIsActive = userWasActive = true;
1675 	clock_get_uptime(&gUserActiveAbsTime);
1676 	setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1677 
1678 	// Set the default system capabilities at boot.
1679 	_currentCapability = kIOPMSystemCapabilityCPU      |
1680 	    kIOPMSystemCapabilityGraphics |
1681 	    kIOPMSystemCapabilityAudio    |
1682 	    kIOPMSystemCapabilityNetwork;
1683 
1684 	_pendingCapability = _currentCapability;
1685 	_desiredCapability = _currentCapability;
1686 	_highestCapability = _currentCapability;
1687 	setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1688 
1689 	queuedSleepWakeUUIDString = NULL;
1690 	initializeBootSessionUUID();
1691 	pmStatsAppResponses     = OSArray::withCapacity(5);
1692 	_statsNameKey           = OSSymbol::withCString(kIOPMStatsNameKey);
1693 	_statsPIDKey            = OSSymbol::withCString(kIOPMStatsPIDKey);
1694 	_statsTimeMSKey         = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1695 	_statsResponseTypeKey   = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1696 	_statsMessageTypeKey    = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1697 	_statsPowerCapsKey      = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1698 	assertOnWakeSecs        = -1;// Invalid value to prevent updates
1699 
1700 	pmStatsLock = IOLockAlloc();
1701 	idxPMCPUClamshell = kCPUUnknownIndex;
1702 	idxPMCPULimitedPower = kCPUUnknownIndex;
1703 
1704 	tmpDict = OSDictionary::withCapacity(1);
1705 	setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1706 
1707 	// Set a default "SystemPowerProfileOverrideDict" for platform
1708 	// drivers without any overrides.
1709 	if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1710 		tmpDict = OSDictionary::withCapacity(1);
1711 		setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1712 	}
1713 
1714 	settingsCallbacks = OSDictionary::withCapacity(1);
1715 
1716 	// Create a list of the valid PM settings that we'll relay to
1717 	// interested clients in setProperties() => setPMSetting()
1718 	allowedPMSettings = OSArray::withObjects(
1719 		(const OSObject **)settingsArr,
1720 		kRootDomainSettingsCount,
1721 		0);
1722 
1723 	// List of PM settings that should not automatically publish itself
1724 	// as a feature when registered by a listener.
1725 	noPublishPMSettings = OSArray::withObjects(
1726 		(const OSObject **)noPublishSettingsArr,
1727 		kRootDomainNoPublishSettingsCount,
1728 		0);
1729 
1730 	fPMSettingsDict = OSDictionary::withCapacity(5);
1731 	preventIdleSleepList = OSSet::withCapacity(8);
1732 	preventSystemSleepList = OSSet::withCapacity(2);
1733 
1734 	PMinit(); // creates gIOPMWorkLoop
1735 	gIOPMWorkLoop = getIOPMWorkloop();
1736 
1737 	// Create IOPMPowerStateQueue used to queue external power
1738 	// events, and to handle those events on the PM work loop.
1739 	pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1740 		this, OSMemberFunctionCast(IOEventSource::Action, this,
1741 		&IOPMrootDomain::dispatchPowerEvent));
1742 	gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1743 
1744 	_aotMode = 0;
1745 	_aotTimerES = IOTimerEventSource::timerEventSource(this,
1746 	    OSMemberFunctionCast(IOTimerEventSource::Action,
1747 	    this, &IOPMrootDomain::aotEvaluate));
1748 	gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1749 
1750 	// Avoid publishing service early so gIOPMWorkLoop is
1751 	// guaranteed to be initialized by rootDomain.
1752 	publishPMRootDomain();
1753 
1754 	// create our power parent
1755 	gPatriarch = new IORootParent;
1756 	gPatriarch->init();
1757 	gPatriarch->attach(this);
1758 	gPatriarch->start(this);
1759 	gPatriarch->addPowerChild(this);
1760 
1761 	registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1762 	changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1763 
1764 	// install power change handler
1765 	gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1766 
1767 #if DISPLAY_WRANGLER_PRESENT
1768 	wranglerIdleSettings = OSDictionary::withCapacity(1);
1769 	OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1770 
1771 	if (wranglerIdleSettings && wranglerIdlePeriod) {
1772 		wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1773 		    wranglerIdlePeriod.get());
1774 	}
1775 
1776 #endif /* DISPLAY_WRANGLER_PRESENT */
1777 
1778 	lowLatencyAudioNotifierDict       = OSDictionary::withCapacity(2);
1779 	lowLatencyAudioNotifyStateSym     = OSSymbol::withCString("LowLatencyAudioNotifyState");
1780 	lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1781 	lowLatencyAudioNotifyStateVal     = OSNumber::withNumber(0ull, 32);
1782 	lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1783 
1784 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1785 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1786 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1787 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1788 	}
1789 
1790 	OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1791 	setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1792 
1793 	// IOBacklightDisplay can take a long time to load at boot, or it may
1794 	// not load at all if you're booting with clamshell closed. We publish
1795 	// 'DisplayDims' here redundantly to get it published early and at all.
1796 	OSSharedPtr<OSDictionary> matching;
1797 	matching = serviceMatching("IOPMPowerSource");
1798 	psIterator = getMatchingServices(matching.get());
1799 
1800 	if (psIterator && psIterator->getNextObject()) {
1801 		// There's at least one battery on the system, so we publish
1802 		// 'DisplayDims' support for the LCD.
1803 		publishFeature("DisplayDims");
1804 	}
1805 
1806 	// read swd_panic boot-arg
1807 	PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1808 	gWillShutdownSysctlRegistered = true;
1809 
1810 #if HIBERNATION
1811 #if defined(__arm64__)
1812 #endif /* defined(__arm64__) */
1813 	IOHibernateSystemInit(this);
1814 #endif
1815 
1816 	registerService();                  // let clients find us
1817 
1818 	return true;
1819 }
1820 
1821 //******************************************************************************
1822 // setProperties
1823 //
1824 // Receive a setProperty call
1825 // The "System Boot" property means the system is completely booted.
1826 //******************************************************************************
1827 
1828 IOReturn
setProperties(OSObject * props_obj)1829 IOPMrootDomain::setProperties( OSObject * props_obj )
1830 {
1831 	IOReturn        return_value = kIOReturnSuccess;
1832 	OSDictionary    *dict = OSDynamicCast(OSDictionary, props_obj);
1833 	OSBoolean       *b = NULL;
1834 	OSNumber        *n = NULL;
1835 	const OSSymbol  *key = NULL;
1836 	OSObject        *obj = NULL;
1837 	OSSharedPtr<OSCollectionIterator> iter;
1838 
1839 	if (!dict) {
1840 		return kIOReturnBadArgument;
1841 	}
1842 
1843 	bool clientEntitled = false;
1844 	{
1845 		OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1846 		clientEntitled = (obj == kOSBooleanTrue);
1847 	}
1848 
1849 	if (!clientEntitled) {
1850 		const char * errorSuffix = NULL;
1851 
1852 		// IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1853 		// That API can set 6 possible keys that are checked below.
1854 		if ((dict->getCount() == 1) &&
1855 		    (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1856 		    dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1857 		    dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1858 		    dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1859 		    dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1860 		    dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1861 			return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1862 			if (return_value != kIOReturnSuccess) {
1863 				errorSuffix = "privileged";
1864 			}
1865 		} else {
1866 			return_value = kIOReturnNotPermitted;
1867 			errorSuffix = "entitled";
1868 		}
1869 
1870 		if (return_value != kIOReturnSuccess) {
1871 			OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1872 			DLOG("%s failed, process %s is not %s\n", __func__,
1873 			    procName ? procName->getCStringNoCopy() : "", errorSuffix);
1874 			return return_value;
1875 		}
1876 	}
1877 
1878 	OSSharedPtr<const OSSymbol> publish_simulated_battery_string    = OSSymbol::withCString("SoftwareSimulatedBatteries");
1879 	OSSharedPtr<const OSSymbol> boot_complete_string                = OSSymbol::withCString("System Boot Complete");
1880 	OSSharedPtr<const OSSymbol> sys_shutdown_string                 = OSSymbol::withCString("System Shutdown");
1881 	OSSharedPtr<const OSSymbol> stall_halt_string                   = OSSymbol::withCString("StallSystemAtHalt");
1882 	OSSharedPtr<const OSSymbol> battery_warning_disabled_string     = OSSymbol::withCString("BatteryWarningsDisabled");
1883 	OSSharedPtr<const OSSymbol> idle_seconds_string                 = OSSymbol::withCString("System Idle Seconds");
1884 	OSSharedPtr<const OSSymbol> idle_milliseconds_string            = OSSymbol::withCString("System Idle Milliseconds");
1885 	OSSharedPtr<const OSSymbol> sleepdisabled_string                = OSSymbol::withCString("SleepDisabled");
1886 	OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string        = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1887 	OSSharedPtr<const OSSymbol> loginwindow_progress_string         = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1888 	OSSharedPtr<const OSSymbol> coredisplay_progress_string         = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1889 	OSSharedPtr<const OSSymbol> coregraphics_progress_string        = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1890 #if DEBUG || DEVELOPMENT
1891 	OSSharedPtr<const OSSymbol> clamshell_close_string              = OSSymbol::withCString("IOPMTestClamshellClose");
1892 	OSSharedPtr<const OSSymbol> clamshell_open_string               = OSSymbol::withCString("IOPMTestClamshellOpen");
1893 	OSSharedPtr<const OSSymbol> ac_detach_string                    = OSSymbol::withCString("IOPMTestACDetach");
1894 	OSSharedPtr<const OSSymbol> ac_attach_string                    = OSSymbol::withCString("IOPMTestACAttach");
1895 	OSSharedPtr<const OSSymbol> desktopmode_set_string              = OSSymbol::withCString("IOPMTestDesktopModeSet");
1896 	OSSharedPtr<const OSSymbol> desktopmode_remove_string           = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1897 #endif
1898 
1899 #if HIBERNATION
1900 	OSSharedPtr<const OSSymbol> hibernatemode_string                = OSSymbol::withCString(kIOHibernateModeKey);
1901 	OSSharedPtr<const OSSymbol> hibernatefile_string                = OSSymbol::withCString(kIOHibernateFileKey);
1902 	OSSharedPtr<const OSSymbol> hibernatefilemin_string             = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1903 	OSSharedPtr<const OSSymbol> hibernatefilemax_string             = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1904 	OSSharedPtr<const OSSymbol> hibernatefreeratio_string           = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1905 	OSSharedPtr<const OSSymbol> hibernatefreetime_string            = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1906 #endif
1907 
1908 	iter = OSCollectionIterator::withCollection(dict);
1909 	if (!iter) {
1910 		return_value = kIOReturnNoMemory;
1911 		goto exit;
1912 	}
1913 
1914 	while ((key = (const OSSymbol *) iter->getNextObject()) &&
1915 	    (obj = dict->getObject(key))) {
1916 		if (key->isEqualTo(publish_simulated_battery_string.get())) {
1917 			if (OSDynamicCast(OSBoolean, obj)) {
1918 				publishResource(key, kOSBooleanTrue);
1919 			}
1920 		} else if (key->isEqualTo(idle_seconds_string.get())) {
1921 			if ((n = OSDynamicCast(OSNumber, obj))) {
1922 				setProperty(key, n);
1923 				idleMilliSeconds = n->unsigned32BitValue() * 1000;
1924 			}
1925 		} else if (key->isEqualTo(idle_milliseconds_string.get())) {
1926 			if ((n = OSDynamicCast(OSNumber, obj))) {
1927 				setProperty(key, n);
1928 				idleMilliSeconds = n->unsigned32BitValue();
1929 			}
1930 		} else if (key->isEqualTo(boot_complete_string.get())) {
1931 			pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1932 		} else if (key->isEqualTo(sys_shutdown_string.get())) {
1933 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1934 				pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1935 			}
1936 		} else if (key->isEqualTo(battery_warning_disabled_string.get())) {
1937 			setProperty(key, obj);
1938 		}
1939 #if HIBERNATION
1940 		else if (key->isEqualTo(hibernatemode_string.get()) ||
1941 		    key->isEqualTo(hibernatefilemin_string.get()) ||
1942 		    key->isEqualTo(hibernatefilemax_string.get()) ||
1943 		    key->isEqualTo(hibernatefreeratio_string.get()) ||
1944 		    key->isEqualTo(hibernatefreetime_string.get())) {
1945 			if ((n = OSDynamicCast(OSNumber, obj))) {
1946 				setProperty(key, n);
1947 			}
1948 		} else if (key->isEqualTo(hibernatefile_string.get())) {
1949 			OSString * str = OSDynamicCast(OSString, obj);
1950 			if (str) {
1951 				setProperty(key, str);
1952 			}
1953 		}
1954 #endif
1955 		else if (key->isEqualTo(sleepdisabled_string.get())) {
1956 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1957 				setProperty(key, b);
1958 				pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1959 			}
1960 		} else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
1961 			obj->retain();
1962 			pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1963 		} else if (key->isEqualTo(loginwindow_progress_string.get())) {
1964 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1965 				uint32_t data = n->unsigned32BitValue();
1966 				pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
1967 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
1968 			}
1969 		} else if (key->isEqualTo(coredisplay_progress_string.get())) {
1970 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1971 				uint32_t data = n->unsigned32BitValue();
1972 				pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
1973 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
1974 			}
1975 		} else if (key->isEqualTo(coregraphics_progress_string.get())) {
1976 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
1977 				uint32_t data = n->unsigned32BitValue();
1978 				pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
1979 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
1980 			}
1981 		} else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
1982 		    key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
1983 		    key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
1984 		    key->isEqualTo(stall_halt_string.get())) {
1985 			if ((b = OSDynamicCast(OSBoolean, obj))) {
1986 				setProperty(key, b);
1987 			}
1988 		} else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1989 		    key->isEqualTo(kIOPMDeepSleepTimerKey) ||
1990 		    key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1991 		    key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
1992 			if ((n = OSDynamicCast(OSNumber, obj))) {
1993 				setProperty(key, n);
1994 			}
1995 		} else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
1996 			if (kOSBooleanTrue == obj) {
1997 				OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
1998 			} else {
1999 				OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2000 			}
2001 			DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2002 		}
2003 #if DEBUG || DEVELOPMENT
2004 		else if (key->isEqualTo(clamshell_close_string.get())) {
2005 			DLOG("SetProperties: setting clamshell close\n");
2006 			UInt32 msg = kIOPMClamshellClosed;
2007 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2008 		} else if (key->isEqualTo(clamshell_open_string.get())) {
2009 			DLOG("SetProperties: setting clamshell open\n");
2010 			UInt32 msg = kIOPMClamshellOpened;
2011 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2012 		} else if (key->isEqualTo(ac_detach_string.get())) {
2013 			DLOG("SetProperties: setting ac detach\n");
2014 			UInt32 msg = kIOPMSetACAdaptorConnected;
2015 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2016 		} else if (key->isEqualTo(ac_attach_string.get())) {
2017 			DLOG("SetProperties: setting ac attach\n");
2018 			UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2019 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2020 		} else if (key->isEqualTo(desktopmode_set_string.get())) {
2021 			DLOG("SetProperties: setting desktopmode");
2022 			UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2023 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2024 		} else if (key->isEqualTo(desktopmode_remove_string.get())) {
2025 			DLOG("SetProperties: removing desktopmode\n");
2026 			UInt32 msg = kIOPMSetDesktopMode;
2027 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2028 		}
2029 #endif
2030 		// Relay our allowed PM settings onto our registered PM clients
2031 		else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2032 			return_value = setPMSetting(key, obj);
2033 			if (kIOReturnSuccess != return_value) {
2034 				break;
2035 			}
2036 		} else {
2037 			DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2038 		}
2039 	}
2040 
2041 exit:
2042 	return return_value;
2043 }
2044 
2045 // MARK: -
2046 // MARK: Aggressiveness
2047 
2048 //******************************************************************************
2049 // setAggressiveness
2050 //
2051 // Override IOService::setAggressiveness()
2052 //******************************************************************************
2053 
2054 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2055 IOPMrootDomain::setAggressiveness(
2056 	unsigned long   type,
2057 	unsigned long   value )
2058 {
2059 	return setAggressiveness( type, value, 0 );
2060 }
2061 
2062 /*
2063  * Private setAggressiveness() with an internal options argument.
2064  */
2065 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2066 IOPMrootDomain::setAggressiveness(
2067 	unsigned long   type,
2068 	unsigned long   value,
2069 	IOOptionBits    options )
2070 {
2071 	AggressivesRequest *    entry;
2072 	AggressivesRequest *    request;
2073 	bool                    found = false;
2074 
2075 	if ((type > UINT_MAX) || (value > UINT_MAX)) {
2076 		return kIOReturnBadArgument;
2077 	}
2078 
2079 	if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2080 		DLOG("setAggressiveness(%x) %s = %u\n",
2081 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2082 	} else {
2083 		DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2084 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2085 	}
2086 
2087 	request = IOMallocType(AggressivesRequest);
2088 	request->options  = options;
2089 	request->dataType = kAggressivesRequestTypeRecord;
2090 	request->data.record.type  = (uint32_t) type;
2091 	request->data.record.value = (uint32_t) value;
2092 
2093 	AGGRESSIVES_LOCK();
2094 
2095 	// Update disk quick spindown flag used by getAggressiveness().
2096 	// Never merge requests with quick spindown flags set.
2097 
2098 	if (options & kAggressivesOptionQuickSpindownEnable) {
2099 		gAggressivesState |= kAggressivesStateQuickSpindown;
2100 	} else if (options & kAggressivesOptionQuickSpindownDisable) {
2101 		gAggressivesState &= ~kAggressivesStateQuickSpindown;
2102 	} else {
2103 		// Coalesce requests with identical aggressives types.
2104 		// Deal with callers that calls us too "aggressively".
2105 
2106 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2107 		{
2108 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2109 			    (entry->data.record.type == type) &&
2110 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2111 				entry->data.record.value = (uint32_t) value;
2112 				found = true;
2113 				break;
2114 			}
2115 		}
2116 	}
2117 
2118 	if (!found) {
2119 		queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2120 	}
2121 
2122 	AGGRESSIVES_UNLOCK();
2123 
2124 	if (found) {
2125 		IOFreeType(request, AggressivesRequest);
2126 	}
2127 
2128 	if (options & kAggressivesOptionSynchronous) {
2129 		handleAggressivesRequests(); // not truly synchronous
2130 	} else {
2131 		thread_call_enter(aggressivesThreadCall);
2132 	}
2133 
2134 	return kIOReturnSuccess;
2135 }
2136 
2137 //******************************************************************************
2138 // getAggressiveness
2139 //
2140 // Override IOService::setAggressiveness()
2141 // Fetch the aggressiveness factor with the given type.
2142 //******************************************************************************
2143 
2144 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2145 IOPMrootDomain::getAggressiveness(
2146 	unsigned long   type,
2147 	unsigned long * outLevel )
2148 {
2149 	uint32_t    value  = 0;
2150 	int         source = 0;
2151 
2152 	if (!outLevel || (type > UINT_MAX)) {
2153 		return kIOReturnBadArgument;
2154 	}
2155 
2156 	AGGRESSIVES_LOCK();
2157 
2158 	// Disk quick spindown in effect, report value = 1
2159 
2160 	if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2161 	    (type == kPMMinutesToSpinDown)) {
2162 		value  = kAggressivesMinValue;
2163 		source = 1;
2164 	}
2165 
2166 	// Consult the pending request queue.
2167 
2168 	if (!source) {
2169 		AggressivesRequest * entry;
2170 
2171 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2172 		{
2173 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2174 			    (entry->data.record.type == type) &&
2175 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2176 				value  = entry->data.record.value;
2177 				source = 2;
2178 				break;
2179 			}
2180 		}
2181 	}
2182 
2183 	// Consult the backend records.
2184 
2185 	if (!source && aggressivesData) {
2186 		AggressivesRecord * record;
2187 		int                 i, count;
2188 
2189 		count  = aggressivesData->getLength() / sizeof(AggressivesRecord);
2190 		record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2191 
2192 		for (i = 0; i < count; i++, record++) {
2193 			if (record->type == type) {
2194 				value  = record->value;
2195 				source = 3;
2196 				break;
2197 			}
2198 		}
2199 	}
2200 
2201 	AGGRESSIVES_UNLOCK();
2202 
2203 	if (source) {
2204 		*outLevel = (unsigned long) value;
2205 		return kIOReturnSuccess;
2206 	} else {
2207 		DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2208 		*outLevel = 0; // default return = 0, driver may not check for error
2209 		return kIOReturnInvalid;
2210 	}
2211 }
2212 
2213 //******************************************************************************
2214 // joinAggressiveness
2215 //
2216 // Request from IOService to join future aggressiveness broadcasts.
2217 //******************************************************************************
2218 
2219 IOReturn
joinAggressiveness(IOService * service)2220 IOPMrootDomain::joinAggressiveness(
2221 	IOService * service )
2222 {
2223 	AggressivesRequest *    request;
2224 
2225 	if (!service || (service == this)) {
2226 		return kIOReturnBadArgument;
2227 	}
2228 
2229 	DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2230 
2231 	request = IOMallocType(AggressivesRequest);
2232 	request->dataType = kAggressivesRequestTypeService;
2233 	request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2234 
2235 	AGGRESSIVES_LOCK();
2236 	queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2237 	AGGRESSIVES_UNLOCK();
2238 
2239 	thread_call_enter(aggressivesThreadCall);
2240 
2241 	return kIOReturnSuccess;
2242 }
2243 
2244 //******************************************************************************
2245 // handleAggressivesRequests
2246 //
2247 // Backend thread processes all incoming aggressiveness requests in the queue.
2248 //******************************************************************************
2249 
2250 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2251 handleAggressivesFunction(
2252 	thread_call_param_t param1,
2253 	thread_call_param_t param2 )
2254 {
2255 	if (param1) {
2256 		((IOPMrootDomain *) param1)->handleAggressivesRequests();
2257 	}
2258 }
2259 
2260 void
handleAggressivesRequests(void)2261 IOPMrootDomain::handleAggressivesRequests( void )
2262 {
2263 	AggressivesRecord *     start;
2264 	AggressivesRecord *     record;
2265 	AggressivesRequest *    request;
2266 	queue_head_t            joinedQueue;
2267 	int                     i, count;
2268 	bool                    broadcast;
2269 	bool                    found;
2270 	bool                    pingSelf = false;
2271 
2272 	AGGRESSIVES_LOCK();
2273 
2274 	if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2275 	    queue_empty(&aggressivesQueue)) {
2276 		goto unlock_done;
2277 	}
2278 
2279 	gAggressivesState |= kAggressivesStateBusy;
2280 	count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2281 	start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2282 
2283 	do{
2284 		broadcast = false;
2285 		queue_init(&joinedQueue);
2286 
2287 		do{
2288 			// Remove request from the incoming queue in FIFO order.
2289 			queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2290 			switch (request->dataType) {
2291 			case kAggressivesRequestTypeRecord:
2292 				// Update existing record if found.
2293 				found = false;
2294 				for (i = 0, record = start; i < count; i++, record++) {
2295 					if (record->type == request->data.record.type) {
2296 						found = true;
2297 
2298 						if (request->options & kAggressivesOptionQuickSpindownEnable) {
2299 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2300 								broadcast = true;
2301 								record->flags |= (kAggressivesRecordFlagMinValue |
2302 								    kAggressivesRecordFlagModified);
2303 								DLOG("disk spindown accelerated, was %u min\n",
2304 								    record->value);
2305 							}
2306 						} else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2307 							if (record->flags & kAggressivesRecordFlagMinValue) {
2308 								broadcast = true;
2309 								record->flags |= kAggressivesRecordFlagModified;
2310 								record->flags &= ~kAggressivesRecordFlagMinValue;
2311 								DLOG("disk spindown restored to %u min\n",
2312 								    record->value);
2313 							}
2314 						} else if (record->value != request->data.record.value) {
2315 							record->value = request->data.record.value;
2316 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2317 								broadcast = true;
2318 								record->flags |= kAggressivesRecordFlagModified;
2319 							}
2320 						}
2321 						break;
2322 					}
2323 				}
2324 
2325 				// No matching record, append a new record.
2326 				if (!found &&
2327 				    ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2328 					AggressivesRecord   newRecord;
2329 
2330 					newRecord.flags = kAggressivesRecordFlagModified;
2331 					newRecord.type  = request->data.record.type;
2332 					newRecord.value = request->data.record.value;
2333 					if (request->options & kAggressivesOptionQuickSpindownEnable) {
2334 						newRecord.flags |= kAggressivesRecordFlagMinValue;
2335 						DLOG("disk spindown accelerated\n");
2336 					}
2337 
2338 					aggressivesData->appendValue(newRecord);
2339 
2340 					// OSData may have switched to another (larger) buffer.
2341 					count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2342 					start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2343 					broadcast = true;
2344 				}
2345 
2346 				// Finished processing the request, release it.
2347 				IOFreeType(request, AggressivesRequest);
2348 				break;
2349 
2350 			case kAggressivesRequestTypeService:
2351 				// synchronizeAggressives() will free request.
2352 				queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2353 				break;
2354 
2355 			default:
2356 				panic("bad aggressives request type %x", request->dataType);
2357 				break;
2358 			}
2359 		} while (!queue_empty(&aggressivesQueue));
2360 
2361 		// Release the lock to perform work, with busy flag set.
2362 		if (!queue_empty(&joinedQueue) || broadcast) {
2363 			AGGRESSIVES_UNLOCK();
2364 			if (!queue_empty(&joinedQueue)) {
2365 				synchronizeAggressives(&joinedQueue, start, count);
2366 			}
2367 			if (broadcast) {
2368 				broadcastAggressives(start, count);
2369 			}
2370 			AGGRESSIVES_LOCK();
2371 		}
2372 
2373 		// Remove the modified flag from all records.
2374 		for (i = 0, record = start; i < count; i++, record++) {
2375 			if ((record->flags & kAggressivesRecordFlagModified) &&
2376 			    ((record->type == kPMMinutesToDim) ||
2377 			    (record->type == kPMMinutesToSleep))) {
2378 				pingSelf = true;
2379 			}
2380 
2381 			record->flags &= ~kAggressivesRecordFlagModified;
2382 		}
2383 
2384 		// Check the incoming queue again since new entries may have been
2385 		// added while lock was released above.
2386 	} while (!queue_empty(&aggressivesQueue));
2387 
2388 	gAggressivesState &= ~kAggressivesStateBusy;
2389 
2390 unlock_done:
2391 	AGGRESSIVES_UNLOCK();
2392 
2393 	// Root domain is interested in system and display sleep slider changes.
2394 	// Submit a power event to handle those changes on the PM work loop.
2395 
2396 	if (pingSelf && pmPowerStateQueue) {
2397 		pmPowerStateQueue->submitPowerEvent(
2398 			kPowerEventPolicyStimulus,
2399 			(void *) kStimulusAggressivenessChanged );
2400 	}
2401 }
2402 
2403 //******************************************************************************
2404 // synchronizeAggressives
2405 //
2406 // Push all known aggressiveness records to one or more IOService.
2407 //******************************************************************************
2408 
2409 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2410 IOPMrootDomain::synchronizeAggressives(
2411 	queue_head_t *              joinedQueue,
2412 	const AggressivesRecord *   array,
2413 	int                         count )
2414 {
2415 	OSSharedPtr<IOService>      service;
2416 	AggressivesRequest *        request;
2417 	const AggressivesRecord *   record;
2418 	IOPMDriverCallEntry         callEntry;
2419 	uint32_t                    value;
2420 	int                         i;
2421 
2422 	while (!queue_empty(joinedQueue)) {
2423 		queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2424 		if (request->dataType == kAggressivesRequestTypeService) {
2425 			// retained by joinAggressiveness(), so take ownership
2426 			service = os::move(request->data.service);
2427 		} else {
2428 			service.reset();
2429 		}
2430 
2431 		IOFreeType(request, AggressivesRequest);
2432 		request = NULL;
2433 
2434 		if (service) {
2435 			if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2436 				for (i = 0, record = array; i < count; i++, record++) {
2437 					value = record->value;
2438 					if (record->flags & kAggressivesRecordFlagMinValue) {
2439 						value = kAggressivesMinValue;
2440 					}
2441 
2442 					_LOG("synchronizeAggressives 0x%x = %u to %s\n",
2443 					    record->type, value, service->getName());
2444 					service->setAggressiveness(record->type, value);
2445 				}
2446 				service->deassertPMDriverCall(&callEntry);
2447 			}
2448 		}
2449 	}
2450 }
2451 
2452 //******************************************************************************
2453 // broadcastAggressives
2454 //
2455 // Traverse PM tree and call setAggressiveness() for records that have changed.
2456 //******************************************************************************
2457 
2458 void
broadcastAggressives(const AggressivesRecord * array,int count)2459 IOPMrootDomain::broadcastAggressives(
2460 	const AggressivesRecord *   array,
2461 	int                         count )
2462 {
2463 	OSSharedPtr<IORegistryIterator> iter;
2464 	IORegistryEntry                *entry;
2465 	OSSharedPtr<IORegistryEntry>    child;
2466 	IOPowerConnection              *connect;
2467 	IOService                      *service;
2468 	const AggressivesRecord        *record;
2469 	IOPMDriverCallEntry             callEntry;
2470 	uint32_t                        value;
2471 	int                             i;
2472 
2473 	iter = IORegistryIterator::iterateOver(
2474 		this, gIOPowerPlane, kIORegistryIterateRecursively);
2475 	if (iter) {
2476 		do{
2477 			// !! reset the iterator
2478 			iter->reset();
2479 			while ((entry = iter->getNextObject())) {
2480 				connect = OSDynamicCast(IOPowerConnection, entry);
2481 				if (!connect || !connect->getReadyFlag()) {
2482 					continue;
2483 				}
2484 
2485 				child = connect->copyChildEntry(gIOPowerPlane);
2486 				if (child) {
2487 					if ((service = OSDynamicCast(IOService, child.get()))) {
2488 						if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2489 							for (i = 0, record = array; i < count; i++, record++) {
2490 								if (record->flags & kAggressivesRecordFlagModified) {
2491 									value = record->value;
2492 									if (record->flags & kAggressivesRecordFlagMinValue) {
2493 										value = kAggressivesMinValue;
2494 									}
2495 									_LOG("broadcastAggressives %x = %u to %s\n",
2496 									    record->type, value, service->getName());
2497 									service->setAggressiveness(record->type, value);
2498 								}
2499 							}
2500 							service->deassertPMDriverCall(&callEntry);
2501 						}
2502 					}
2503 				}
2504 			}
2505 		}while (!entry && !iter->isValid());
2506 	}
2507 }
2508 
2509 //*****************************************
2510 // stackshot on power button press
2511 // ***************************************
2512 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2513 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2514 {
2515 	/* Power button pressed during wake
2516 	 * Take a stackshot
2517 	 */
2518 	DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2519 	((IOPMrootDomain *)us)->takeStackshot(false);
2520 }
2521 
2522 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2523 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2524 {
2525 	/* Power button released.
2526 	 * Delete any stackshot data
2527 	 */
2528 	DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2529 	((IOPMrootDomain *)us)->deleteStackshot();
2530 }
2531 //*************************************************************************
2532 //
2533 
2534 // MARK: -
2535 // MARK: System Sleep
2536 
2537 //******************************************************************************
2538 // startIdleSleepTimer
2539 //
2540 //******************************************************************************
2541 
2542 void
startIdleSleepTimer(uint32_t inMilliSeconds)2543 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2544 {
2545 	AbsoluteTime deadline;
2546 
2547 	ASSERT_GATED();
2548 	if (gNoIdleFlag) {
2549 		DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2550 		return;
2551 	}
2552 	if (inMilliSeconds) {
2553 		if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2554 			AbsoluteTime    now;
2555 			uint64_t        nsec_since_wake;
2556 			uint64_t                msec_since_wake;
2557 
2558 			// Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2559 			// after the most recent AP wake.
2560 			clock_get_uptime(&now);
2561 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2562 			absolutetime_to_nanoseconds(now, &nsec_since_wake);
2563 			msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2564 
2565 			if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2566 				uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2567 
2568 				// Ensure that our new idle timer is not less than inMilliSeconds,
2569 				// as we should only be increasing the timer duration, not decreasing it
2570 				if (newIdleTimer > inMilliSeconds) {
2571 					DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2572 					inMilliSeconds = newIdleTimer;
2573 				}
2574 			}
2575 		}
2576 		clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2577 		thread_call_enter_delayed(extraSleepTimer, deadline);
2578 		idleSleepTimerPending = true;
2579 	} else {
2580 		thread_call_enter(extraSleepTimer);
2581 	}
2582 	DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2583 }
2584 
2585 //******************************************************************************
2586 // cancelIdleSleepTimer
2587 //
2588 //******************************************************************************
2589 
2590 void
cancelIdleSleepTimer(void)2591 IOPMrootDomain::cancelIdleSleepTimer( void )
2592 {
2593 	ASSERT_GATED();
2594 	if (idleSleepTimerPending) {
2595 		DLOG("idle timer cancelled\n");
2596 		thread_call_cancel(extraSleepTimer);
2597 		idleSleepTimerPending = false;
2598 
2599 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2600 			AbsoluteTime    now;
2601 			clock_usec_t    microsecs;
2602 			clock_get_uptime(&now);
2603 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2604 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2605 			if (assertOnWakeReport) {
2606 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2607 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2608 			}
2609 		}
2610 	}
2611 }
2612 
2613 //******************************************************************************
2614 // idleSleepTimerExpired
2615 //
2616 //******************************************************************************
2617 
2618 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2619 idleSleepTimerExpired(
2620 	thread_call_param_t us, thread_call_param_t )
2621 {
2622 	((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2623 }
2624 
2625 //******************************************************************************
2626 // handleSleepTimerExpiration
2627 //
2628 // The time between the sleep idle timeout and the next longest one has elapsed.
2629 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2630 //******************************************************************************
2631 
2632 void
handleSleepTimerExpiration(void)2633 IOPMrootDomain::handleSleepTimerExpiration( void )
2634 {
2635 	if (!gIOPMWorkLoop->inGate()) {
2636 		gIOPMWorkLoop->runAction(
2637 			OSMemberFunctionCast(IOWorkLoop::Action, this,
2638 			&IOPMrootDomain::handleSleepTimerExpiration),
2639 			this);
2640 		return;
2641 	}
2642 
2643 	DLOG("sleep timer expired\n");
2644 	ASSERT_GATED();
2645 
2646 	idleSleepTimerPending = false;
2647 	setQuickSpinDownTimeout();
2648 	adjustPowerState(true);
2649 }
2650 
2651 //******************************************************************************
2652 // getTimeToIdleSleep
2653 //
2654 // Returns number of milliseconds left before going into idle sleep.
2655 // Caller has to make sure that idle sleep is allowed at the time of calling
2656 // this function
2657 //******************************************************************************
2658 
2659 uint32_t
getTimeToIdleSleep(void)2660 IOPMrootDomain::getTimeToIdleSleep( void )
2661 {
2662 	AbsoluteTime    now, lastActivityTime;
2663 	uint64_t        nanos;
2664 	uint32_t        minutesSinceUserInactive = 0;
2665 	uint32_t        sleepDelay = 0;
2666 
2667 	if (!idleSleepEnabled) {
2668 		return 0xffffffff;
2669 	}
2670 
2671 	if (userActivityTime) {
2672 		lastActivityTime = userActivityTime;
2673 	} else {
2674 		lastActivityTime = userBecameInactiveTime;
2675 	}
2676 
2677 	// Ignore any lastActivityTime that predates the last system wake.
2678 	// The goal is to avoid a sudden idle sleep right after a dark wake
2679 	// due to sleepDelay=0 computed below. The alternative 60s minimum
2680 	// timeout should be large enough to allow dark wake to complete,
2681 	// at which point the idle timer will be promptly cancelled.
2682 	clock_get_uptime(&now);
2683 	if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2684 	    (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2685 		SUB_ABSOLUTETIME(&now, &lastActivityTime);
2686 		absolutetime_to_nanoseconds(now, &nanos);
2687 		minutesSinceUserInactive = nanos / (60000000000ULL);
2688 
2689 		if (minutesSinceUserInactive >= sleepSlider) {
2690 			sleepDelay = 0;
2691 		} else {
2692 			sleepDelay = sleepSlider - minutesSinceUserInactive;
2693 		}
2694 	} else {
2695 		DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2696 		    lastActivityTime, now, gIOLastWakeAbsTime);
2697 		sleepDelay = sleepSlider;
2698 	}
2699 
2700 	DLOG("user inactive %u min, time to idle sleep %u min\n",
2701 	    minutesSinceUserInactive, sleepDelay);
2702 
2703 	return sleepDelay * 60 * 1000;
2704 }
2705 
2706 //******************************************************************************
2707 // setQuickSpinDownTimeout
2708 //
2709 //******************************************************************************
2710 
2711 void
setQuickSpinDownTimeout(void)2712 IOPMrootDomain::setQuickSpinDownTimeout( void )
2713 {
2714 	ASSERT_GATED();
2715 	setAggressiveness(
2716 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2717 }
2718 
2719 //******************************************************************************
2720 // restoreUserSpinDownTimeout
2721 //
2722 //******************************************************************************
2723 
2724 void
restoreUserSpinDownTimeout(void)2725 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2726 {
2727 	ASSERT_GATED();
2728 	setAggressiveness(
2729 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2730 }
2731 
2732 //******************************************************************************
2733 // sleepSystem
2734 //
2735 //******************************************************************************
2736 
2737 /* public */
2738 IOReturn
sleepSystem(void)2739 IOPMrootDomain::sleepSystem( void )
2740 {
2741 	return sleepSystemOptions(NULL);
2742 }
2743 
2744 /* private */
2745 IOReturn
sleepSystemOptions(OSDictionary * options)2746 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2747 {
2748 	OSObject *obj = NULL;
2749 	OSString *reason = NULL;
2750 	/* sleepSystem is a public function, and may be called by any kernel driver.
2751 	 * And that's bad - drivers should sleep the system by calling
2752 	 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2753 	 *
2754 	 * Note that user space app calls to IOPMSleepSystem() will also travel
2755 	 * this code path and thus be correctly identified as software sleeps.
2756 	 */
2757 
2758 	if (options && options->getObject("OSSwitch")) {
2759 		// Log specific sleep cause for OS Switch hibernation
2760 		return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2761 	}
2762 
2763 	if (options && (obj = options->getObject("Sleep Reason"))) {
2764 		reason = OSDynamicCast(OSString, obj);
2765 		if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2766 			return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2767 		}
2768 		if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2769 			return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2770 		}
2771 	}
2772 
2773 	return privateSleepSystem( kIOPMSleepReasonSoftware);
2774 }
2775 
2776 /* private */
2777 IOReturn
privateSleepSystem(uint32_t sleepReason)2778 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2779 {
2780 	/* Called from both gated and non-gated context */
2781 
2782 	if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2783 		return kIOReturnNotPermitted;
2784 	}
2785 
2786 	pmPowerStateQueue->submitPowerEvent(
2787 		kPowerEventPolicyStimulus,
2788 		(void *) kStimulusDemandSystemSleep,
2789 		sleepReason);
2790 
2791 	return kIOReturnSuccess;
2792 }
2793 
2794 //******************************************************************************
2795 // powerChangeDone
2796 //
2797 // This overrides powerChangeDone in IOService.
2798 //******************************************************************************
2799 void
powerChangeDone(unsigned long previousPowerState)2800 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2801 {
2802 #if !__i386__ && !__x86_64__
2803 	uint64_t    timeSinceReset = 0;
2804 #endif
2805 	uint64_t           now;
2806 	unsigned long      newState;
2807 	clock_sec_t        secs;
2808 	clock_usec_t       microsecs;
2809 	uint32_t           lastDebugWakeSeconds;
2810 	clock_sec_t        adjWakeTime;
2811 	IOPMCalendarStruct nowCalendar;
2812 
2813 	ASSERT_GATED();
2814 	newState = getPowerState();
2815 	DLOG("PowerChangeDone: %s->%s\n",
2816 	    getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2817 
2818 	if (previousPowerState == newState) {
2819 		return;
2820 	}
2821 
2822 	notifierThread = current_thread();
2823 	switch (getPowerState()) {
2824 	case SLEEP_STATE: {
2825 		if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2826 			secs = 0;
2827 			microsecs = 0;
2828 			PEGetUTCTimeOfDay(&secs, &microsecs);
2829 
2830 			adjWakeTime = 0;
2831 			if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2832 				IOLog("use _calendarWakeAlarmUTC\n");
2833 				adjWakeTime = _calendarWakeAlarmUTC;
2834 			} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2835 				IOLog("accelerate _aotWakeTime for exit\n");
2836 				adjWakeTime = secs;
2837 			} else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2838 				IOLog("accelerate _aotWakeTime for assertion\n");
2839 				adjWakeTime = secs;
2840 			}
2841 			if (adjWakeTime) {
2842 				IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2843 			}
2844 
2845 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2846 			IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2847 
2848 			IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2849 			assert(kIOReturnSuccess == ret);
2850 		}
2851 		if (_aotLastWakeTime) {
2852 			_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2853 			if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2854 				strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2855 				    gWakeReasonString,
2856 				    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2857 			}
2858 		}
2859 		_aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2860 		if (_aotTimerScheduled) {
2861 			_aotTimerES->cancelTimeout();
2862 			_aotTimerScheduled = false;
2863 		}
2864 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2865 
2866 		// re-enable this timer for next sleep
2867 		cancelIdleSleepTimer();
2868 
2869 		if (clamshellExists) {
2870 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
2871 			if (gClamshellFlags & kClamshell_WAR_58009435) {
2872 				// Disable clamshell sleep until system has completed full wake.
2873 				// This prevents a system sleep request (due to a clamshell close)
2874 				// from being queued until the end of system full wake - even if
2875 				// other clamshell disable bits outside of our control is wrong.
2876 				setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
2877 			}
2878 #endif
2879 
2880 			// Log the last known clamshell state before system sleep
2881 			DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
2882 			    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
2883 			    desktopMode, acAdaptorConnected);
2884 		}
2885 
2886 		clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
2887 		logtime(secs);
2888 		gIOLastSleepTime.tv_sec  = secs;
2889 		gIOLastSleepTime.tv_usec = microsecs;
2890 		if (!_aotLastWakeTime) {
2891 			gIOLastUserSleepTime = gIOLastSleepTime;
2892 		}
2893 
2894 		gIOLastWakeTime.tv_sec = 0;
2895 		gIOLastWakeTime.tv_usec = 0;
2896 		gIOLastSleepAbsTime = now;
2897 
2898 		if (wake2DarkwakeDelay && sleepDelaysReport) {
2899 			clock_sec_t     wake2DarkwakeSecs, darkwake2SleepSecs;
2900 			// Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
2901 
2902 			SUB_ABSOLUTETIME(&now, &ts_sleepStart);
2903 			absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
2904 			absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
2905 			HISTREPORT_TALLYVALUE(sleepDelaysReport,
2906 			    (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
2907 
2908 			DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
2909 			wake2DarkwakeDelay = 0;
2910 		}
2911 #if HIBERNATION
2912 		LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2913 #if (DEVELOPMENT || DEBUG)
2914 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2915 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2916 		    "System State",
2917 		    gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
2918 		    );
2919 #endif /* DEVELOPMENT || DEBUG */
2920 		IOHibernateSystemHasSlept();
2921 
2922 		evaluateSystemSleepPolicyFinal();
2923 #else
2924 		LOG("System Sleep\n");
2925 #if (DEVELOPMENT || DEBUG)
2926 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2927 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2928 		    "System State", "Enter Sleep");
2929 #endif /* DEVELOPMENT || DEBUG */
2930 #endif
2931 		if (thermalWarningState) {
2932 			OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
2933 			if (event) {
2934 				systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
2935 			}
2936 		}
2937 		assertOnWakeSecs = 0;
2938 		lowBatteryCondition = false;
2939 		thermalEmergencyState = false;
2940 
2941 #if DEVELOPMENT || DEBUG
2942 		extern int g_should_log_clock_adjustments;
2943 		if (g_should_log_clock_adjustments) {
2944 			clock_sec_t  secs = 0;
2945 			clock_usec_t microsecs = 0;
2946 			uint64_t now_b = mach_absolute_time();
2947 
2948 			secs = 0;
2949 			microsecs = 0;
2950 			PEGetUTCTimeOfDay(&secs, &microsecs);
2951 
2952 			uint64_t now_a = mach_absolute_time();
2953 			os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
2954 			    __func__, (unsigned long)secs, microsecs, now_b, now_a);
2955 		}
2956 #endif
2957 
2958 		getPlatform()->sleepKernel();
2959 
2960 		// The CPU(s) are off at this point,
2961 		// Code will resume execution here upon wake.
2962 
2963 		clock_get_uptime(&gIOLastWakeAbsTime);
2964 		IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
2965 #if DEVELOPMENT || DEBUG
2966 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
2967 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
2968 		    "System State", "Waking Up"
2969 		    );
2970 #endif /* DEVELOPMENT || DEBUG */
2971 		_highestCapability = 0;
2972 
2973 #if HIBERNATION
2974 		IOHibernateSystemWake();
2975 #endif
2976 
2977 		// sleep transition complete
2978 		gSleepOrShutdownPending = 0;
2979 
2980 		// trip the reset of the calendar clock
2981 		clock_wakeup_calendar();
2982 		clock_get_calendar_microtime(&secs, &microsecs);
2983 		gIOLastWakeTime.tv_sec  = secs;
2984 		gIOLastWakeTime.tv_usec = microsecs;
2985 
2986 		// aot
2987 		if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
2988 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
2989 			secs = 0;
2990 			microsecs = 0;
2991 			PEGetUTCTimeOfDay(&secs, &microsecs);
2992 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2993 			IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2994 			_aotMetrics->sleepCount++;
2995 			_aotLastWakeTime = gIOLastWakeAbsTime;
2996 			if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
2997 				_aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
2998 				        = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
2999 				_aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3000 				        = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3001 			}
3002 
3003 			if (_aotTestTime) {
3004 				if (_aotWakeTimeUTC <= secs) {
3005 					_aotTestTime = _aotTestTime + _aotTestInterval;
3006 				}
3007 				setWakeTime(_aotTestTime);
3008 			}
3009 		}
3010 
3011 #if HIBERNATION
3012 		LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3013 #endif
3014 
3015 		lastSleepReason = 0;
3016 
3017 		lastDebugWakeSeconds    = _debugWakeSeconds;
3018 		_debugWakeSeconds       = 0;
3019 		_scheduledAlarmMask     = 0;
3020 		_nextScheduledAlarmType = NULL;
3021 
3022 		darkWakeExit            = false;
3023 		darkWakePowerClamped    = false;
3024 		darkWakePostTickle      = false;
3025 		darkWakeHibernateError  = false;
3026 		darkWakeToSleepASAP     = true;
3027 		darkWakeLogClamp        = true;
3028 		sleepTimerMaintenance   = false;
3029 		sleepToStandby          = false;
3030 		wranglerTickled         = false;
3031 		userWasActive           = false;
3032 		isRTCAlarmWake          = false;
3033 		clamshellIgnoreClose    = false;
3034 		fullWakeReason = kFullWakeReasonNone;
3035 
3036 #if defined(__i386__) || defined(__x86_64__)
3037 		kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3038 
3039 		OSSharedPtr<OSObject> wakeTypeProp   = copyProperty(kIOPMRootDomainWakeTypeKey);
3040 		OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3041 		OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3042 		OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3043 
3044 		if (wakeReason && (wakeReason->getLength() >= 2) &&
3045 		    gWakeReasonString[0] == '\0') {
3046 			WAKEEVENT_LOCK();
3047 			// Until the platform driver can claim its wake reasons
3048 			strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3049 			    sizeof(gWakeReasonString));
3050 			if (!gWakeReasonSysctlRegistered) {
3051 				gWakeReasonSysctlRegistered = true;
3052 			}
3053 			WAKEEVENT_UNLOCK();
3054 		}
3055 
3056 		if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3057 			lowBatteryCondition = true;
3058 			darkWakeMaintenance = true;
3059 		} else {
3060 #if HIBERNATION
3061 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3062 			OSNumber * hibOptions = OSDynamicCast(  OSNumber, hibOptionsProp.get());
3063 			if (hibernateAborted || ((hibOptions &&
3064 			    !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3065 				// Hibernate aborted, or EFI brought up graphics
3066 				darkWakeExit = true;
3067 				if (hibernateAborted) {
3068 					DLOG("Hibernation aborted\n");
3069 				} else {
3070 					DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3071 				}
3072 			} else
3073 #endif
3074 			if (wakeType && (
3075 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3076 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3077 				// User wake or RTC alarm
3078 				darkWakeExit = true;
3079 				if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3080 					isRTCAlarmWake = true;
3081 				}
3082 			} else if (wakeType &&
3083 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3084 				// SMC standby timer trumps SleepX
3085 				darkWakeMaintenance = true;
3086 				sleepTimerMaintenance = true;
3087 			} else if ((lastDebugWakeSeconds != 0) &&
3088 			    ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3089 				// SleepX before maintenance
3090 				darkWakeExit = true;
3091 			} else if (wakeType &&
3092 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3093 				darkWakeMaintenance = true;
3094 			} else if (wakeType &&
3095 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3096 				darkWakeMaintenance = true;
3097 				darkWakeSleepService = true;
3098 #if HIBERNATION
3099 				if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3100 					sleepToStandby = true;
3101 				}
3102 #endif
3103 			} else if (wakeType &&
3104 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3105 				darkWakeMaintenance = true;
3106 				darkWakeHibernateError = true;
3107 			} else {
3108 				// Unidentified wake source, resume to full wake if debug
3109 				// alarm is pending.
3110 
3111 				if (lastDebugWakeSeconds &&
3112 				    (!wakeReason || wakeReason->isEqualTo(""))) {
3113 					darkWakeExit = true;
3114 				}
3115 			}
3116 		}
3117 
3118 		if (darkWakeExit) {
3119 			darkWakeToSleepASAP = false;
3120 			fullWakeReason = kFullWakeReasonLocalUser;
3121 			reportUserInput();
3122 		} else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3123 			handleSetDisplayPowerOn(true);
3124 		} else if (!darkWakeMaintenance) {
3125 			// Early/late tickle for non-maintenance wake.
3126 			if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3127 				darkWakePostTickle = true;
3128 			}
3129 		}
3130 #else   /* !__i386__ && !__x86_64__ */
3131 		timeSinceReset = ml_get_time_since_reset();
3132 		kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3133 
3134 		if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3135 			wranglerTickled = true;
3136 			fullWakeReason = kFullWakeReasonLocalUser;
3137 			requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3138 		} else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3139 			isRTCAlarmWake = true;
3140 			fullWakeReason = kFullWakeReasonLocalUser;
3141 			requestUserActive(this, "RTC debug alarm");
3142 		} else {
3143 #if HIBERNATION
3144 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3145 			OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3146 			if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3147 				fullWakeReason = kFullWakeReasonLocalUser;
3148 				requestUserActive(this, "hibernate user wake");
3149 			}
3150 #endif
3151 		}
3152 
3153 		// stay awake for at least 30 seconds
3154 		startIdleSleepTimer(30 * 1000);
3155 #endif
3156 		sleepCnt++;
3157 
3158 		thread_call_enter(updateConsoleUsersEntry);
3159 
3160 		// Skip AOT_STATE if we are waking up from an RTC timer.
3161 		// This check needs to be done after the epoch change is processed
3162 		// and before the changePowerStateWithTagToPriv() call below.
3163 		WAKEEVENT_LOCK();
3164 		aotShouldExit(false, false);
3165 		WAKEEVENT_UNLOCK();
3166 
3167 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonWake);
3168 		break;
3169 	}
3170 #if !__i386__ && !__x86_64__
3171 	case ON_STATE:
3172 	case AOT_STATE:
3173 	{
3174 		DLOG("Force re-evaluating aggressiveness\n");
3175 		/* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3176 		pmPowerStateQueue->submitPowerEvent(
3177 			kPowerEventPolicyStimulus,
3178 			(void *) kStimulusNoIdleSleepPreventers );
3179 
3180 		// After changing to ON_STATE, invalidate any previously queued
3181 		// request to change to a state less than ON_STATE. This isn't
3182 		// necessary for AOT_STATE or if the device has only one running
3183 		// state since the changePowerStateToPriv() issued at the tail
3184 		// end of SLEEP_STATE case should take care of that.
3185 		if (getPowerState() == ON_STATE) {
3186 			changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3187 		}
3188 		break;
3189 	}
3190 #endif /* !__i386__ && !__x86_64__ */
3191 	}
3192 	notifierThread = NULL;
3193 }
3194 
3195 //******************************************************************************
3196 // requestPowerDomainState
3197 //
3198 // Extend implementation in IOService. Running on PM work loop thread.
3199 //******************************************************************************
3200 
3201 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3202 IOPMrootDomain::requestPowerDomainState(
3203 	IOPMPowerFlags      childDesire,
3204 	IOPowerConnection * childConnection,
3205 	unsigned long       specification )
3206 {
3207 	// Idle and system sleep prevention flags affects driver desire.
3208 	// Children desire are irrelevant so they are cleared.
3209 
3210 	return super::requestPowerDomainState(0, childConnection, specification);
3211 }
3212 
3213 
3214 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3215 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3216 {
3217 	if (!preventers->getCount()) {
3218 		return;
3219 	}
3220 
3221 	char *buf_iter = buf + strlen(buf);
3222 	char *buf_end = buf + buf_size;
3223 
3224 	OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3225 	OSObject *obj = NULL;
3226 
3227 	while ((obj = iterator->getNextObject())) {
3228 		IOService *srv = OSDynamicCast(IOService, obj);
3229 		if (buf_iter < buf_end) {
3230 			buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3231 		} else {
3232 			DLOG("Print buffer exhausted for sleep preventers list\n");
3233 			break;
3234 		}
3235 	}
3236 }
3237 
3238 //******************************************************************************
3239 // updatePreventIdleSleepList
3240 //
3241 // Called by IOService on PM work loop.
3242 // Returns true if PM policy recognized the driver's desire to prevent idle
3243 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3244 //******************************************************************************
3245 
3246 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3247 IOPMrootDomain::updatePreventIdleSleepList(
3248 	IOService * service, bool addNotRemove)
3249 {
3250 	unsigned int oldCount;
3251 
3252 	oldCount = idleSleepPreventersCount();
3253 	return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3254 }
3255 
3256 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3257 IOPMrootDomain::updatePreventIdleSleepListInternal(
3258 	IOService * service, bool addNotRemove, unsigned int oldCount)
3259 {
3260 	unsigned int newCount;
3261 
3262 	ASSERT_GATED();
3263 
3264 #if defined(XNU_TARGET_OS_OSX)
3265 	// Only the display wrangler and no-idle-sleep kernel assertions
3266 	// can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3267 	// reported by drivers in their power state table is ignored.
3268 	if (service && (service != wrangler) && (service != this)) {
3269 		return false;
3270 	}
3271 #endif
3272 
3273 	if (service) {
3274 		if (addNotRemove) {
3275 			preventIdleSleepList->setObject(service);
3276 			DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3277 			    service->getName(), preventIdleSleepList->getCount());
3278 		} else if (preventIdleSleepList->member(service)) {
3279 			preventIdleSleepList->removeObject(service);
3280 			DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3281 			    service->getName(), preventIdleSleepList->getCount());
3282 		}
3283 
3284 		if (preventIdleSleepList->getCount()) {
3285 			char buf[256] = "Idle Sleep Preventers:";
3286 			makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3287 			DLOG("%s\n", buf);
3288 		}
3289 	}
3290 
3291 	newCount = idleSleepPreventersCount();
3292 
3293 	if ((oldCount == 0) && (newCount != 0)) {
3294 		// Driver added to empty prevent list.
3295 		// Update the driver desire to prevent idle sleep.
3296 		// Driver desire does not prevent demand sleep.
3297 
3298 		changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3299 	} else if ((oldCount != 0) && (newCount == 0)) {
3300 		// Last driver removed from prevent list.
3301 		// Drop the driver clamp to allow idle sleep.
3302 
3303 		changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3304 		evaluatePolicy( kStimulusNoIdleSleepPreventers );
3305 	}
3306 	messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3307 	    &newCount, sizeof(newCount));
3308 
3309 #if defined(XNU_TARGET_OS_OSX)
3310 	if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3311 		DLOG("Cannot cancel idle sleep\n");
3312 		return false; // do not idle-cancel
3313 	}
3314 #endif
3315 
3316 	return true;
3317 }
3318 
3319 //******************************************************************************
3320 // startSpinDump
3321 //******************************************************************************
3322 
3323 void
startSpinDump(uint32_t spindumpKind)3324 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3325 {
3326 	messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3327 }
3328 
3329 //******************************************************************************
3330 // preventSystemSleepListUpdate
3331 //
3332 // Called by IOService on PM work loop.
3333 //******************************************************************************
3334 
3335 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3336 IOPMrootDomain::updatePreventSystemSleepList(
3337 	IOService * service, bool addNotRemove )
3338 {
3339 	unsigned int oldCount, newCount;
3340 
3341 	ASSERT_GATED();
3342 	if (this == service) {
3343 		return;
3344 	}
3345 
3346 	oldCount = preventSystemSleepList->getCount();
3347 	if (addNotRemove) {
3348 		preventSystemSleepList->setObject(service);
3349 		DLOG("Added %s to system sleep preventers list (Total %u)\n",
3350 		    service->getName(), preventSystemSleepList->getCount());
3351 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3352 			AbsoluteTime    now;
3353 			clock_usec_t    microsecs;
3354 			clock_get_uptime(&now);
3355 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3356 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
3357 			if (assertOnWakeReport) {
3358 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3359 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3360 			}
3361 		}
3362 	} else if (preventSystemSleepList->member(service)) {
3363 		preventSystemSleepList->removeObject(service);
3364 		DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3365 		    service->getName(), preventSystemSleepList->getCount());
3366 
3367 		if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3368 			// Lost all system sleep preventers.
3369 			// Send stimulus if system sleep was blocked, and is in dark wake.
3370 			evaluatePolicy( kStimulusDarkWakeEvaluate );
3371 		}
3372 	}
3373 
3374 	newCount = preventSystemSleepList->getCount();
3375 	if (newCount) {
3376 		char buf[256] = "System Sleep Preventers:";
3377 		makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3378 		DLOG("%s\n", buf);
3379 	}
3380 
3381 	messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3382 	    &newCount, sizeof(newCount));
3383 }
3384 
3385 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3386 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3387 {
3388 	OSSharedPtr<OSCollectionIterator> iterator;
3389 	OSObject    *object = NULL;
3390 	OSSharedPtr<OSArray>     array;
3391 
3392 	if (!gIOPMWorkLoop->inGate()) {
3393 		gIOPMWorkLoop->runAction(
3394 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3395 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3396 			this, (void *)idleSleepList, (void *)systemSleepList);
3397 		return;
3398 	}
3399 
3400 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3401 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3402 		array = OSArray::withCapacity(5);
3403 
3404 		if (iterator && array) {
3405 			while ((object = iterator->getNextObject())) {
3406 				IOService *service = OSDynamicCast(IOService, object);
3407 				if (service) {
3408 					OSSharedPtr<const OSSymbol> name = service->copyName();
3409 					if (name) {
3410 						array->setObject(name.get());
3411 					}
3412 				}
3413 			}
3414 		}
3415 		*idleSleepList = array.detach();
3416 	}
3417 
3418 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3419 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3420 		array = OSArray::withCapacity(5);
3421 
3422 		if (iterator && array) {
3423 			while ((object = iterator->getNextObject())) {
3424 				IOService *service = OSDynamicCast(IOService, object);
3425 				if (service) {
3426 					OSSharedPtr<const OSSymbol> name = service->copyName();
3427 					if (name) {
3428 						array->setObject(name.get());
3429 					}
3430 				}
3431 			}
3432 		}
3433 		*systemSleepList = array.detach();
3434 	}
3435 }
3436 
3437 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3438 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3439 {
3440 	OSSharedPtr<OSCollectionIterator> iterator;
3441 	OSObject    *object = NULL;
3442 	OSSharedPtr<OSArray>     array;
3443 
3444 	if (!gIOPMWorkLoop->inGate()) {
3445 		gIOPMWorkLoop->runAction(
3446 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3447 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3448 			this, (void *)idleSleepList, (void *)systemSleepList);
3449 		return;
3450 	}
3451 
3452 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3453 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3454 		array = OSArray::withCapacity(5);
3455 
3456 		if (iterator && array) {
3457 			while ((object = iterator->getNextObject())) {
3458 				IOService *service = OSDynamicCast(IOService, object);
3459 				if (service) {
3460 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3461 					OSSharedPtr<const OSSymbol> name = service->copyName();
3462 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3463 					if (dict && name && id) {
3464 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3465 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3466 						array->setObject(dict.get());
3467 					}
3468 				}
3469 			}
3470 		}
3471 		*idleSleepList = array.detach();
3472 	}
3473 
3474 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3475 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3476 		array = OSArray::withCapacity(5);
3477 
3478 		if (iterator && array) {
3479 			while ((object = iterator->getNextObject())) {
3480 				IOService *service = OSDynamicCast(IOService, object);
3481 				if (service) {
3482 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3483 					OSSharedPtr<const OSSymbol> name = service->copyName();
3484 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3485 					if (dict && name && id) {
3486 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3487 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3488 						array->setObject(dict.get());
3489 					}
3490 				}
3491 			}
3492 		}
3493 		*systemSleepList = array.detach();
3494 	}
3495 }
3496 
3497 //******************************************************************************
3498 // tellChangeDown
3499 //
3500 // Override the superclass implementation to send a different message type.
3501 //******************************************************************************
3502 
3503 bool
tellChangeDown(unsigned long stateNum)3504 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3505 {
3506 	DLOG("tellChangeDown %s->%s\n",
3507 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3508 
3509 	if (SLEEP_STATE == stateNum) {
3510 		// Legacy apps were already told in the full->dark transition
3511 		if (!ignoreTellChangeDown) {
3512 			tracePoint( kIOPMTracePointSleepApplications );
3513 		} else {
3514 			tracePoint( kIOPMTracePointSleepPriorityClients );
3515 		}
3516 	}
3517 
3518 	if (!ignoreTellChangeDown) {
3519 		userActivityAtSleep = userActivityCount;
3520 		DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3521 
3522 		if (SLEEP_STATE == stateNum) {
3523 			hibernateAborted = false;
3524 
3525 			// Direct callout into OSKext so it can disable kext unloads
3526 			// during sleep/wake to prevent deadlocks.
3527 			OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3528 
3529 			IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3530 
3531 			// Two change downs are sent by IOServicePM. Ignore the 2nd.
3532 			// But tellClientsWithResponse() must be called for both.
3533 			ignoreTellChangeDown = true;
3534 		}
3535 	}
3536 
3537 	return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3538 }
3539 
3540 //******************************************************************************
3541 // askChangeDown
3542 //
3543 // Override the superclass implementation to send a different message type.
3544 // This must be idle sleep since we don't ask during any other power change.
3545 //******************************************************************************
3546 
3547 bool
askChangeDown(unsigned long stateNum)3548 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3549 {
3550 	DLOG("askChangeDown %s->%s\n",
3551 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3552 
3553 	// Don't log for dark wake entry
3554 	if (kSystemTransitionSleep == _systemTransitionType) {
3555 		tracePoint( kIOPMTracePointSleepApplications );
3556 	}
3557 
3558 	return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3559 }
3560 
3561 //******************************************************************************
3562 // askChangeDownDone
3563 //
3564 // An opportunity for root domain to cancel the power transition,
3565 // possibily due to an assertion created by powerd in response to
3566 // kIOMessageCanSystemSleep.
3567 //
3568 // Idle sleep:
3569 //   full -> dark wake transition
3570 //     1. Notify apps and powerd with kIOMessageCanSystemSleep
3571 //     2. askChangeDownDone()
3572 //   dark -> sleep transition
3573 //     1. Notify powerd with kIOMessageCanSystemSleep
3574 //     2. askChangeDownDone()
3575 //
3576 // Demand sleep:
3577 //   full -> dark wake transition
3578 //     1. Notify powerd with kIOMessageCanSystemSleep
3579 //     2. askChangeDownDone()
3580 //   dark -> sleep transition
3581 //     1. Notify powerd with kIOMessageCanSystemSleep
3582 //     2. askChangeDownDone()
3583 //******************************************************************************
3584 
3585 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3586 IOPMrootDomain::askChangeDownDone(
3587 	IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3588 {
3589 	DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3590 	    *inOutChangeFlags, *cancel,
3591 	    _systemTransitionType,
3592 	    _currentCapability, _pendingCapability);
3593 
3594 	if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3595 		// Dark->Sleep transition.
3596 		// Check if there are any deny sleep assertions.
3597 		// lastSleepReason already set by handleOurPowerChangeStart()
3598 
3599 		if (!checkSystemCanSleep(lastSleepReason)) {
3600 			// Cancel dark wake to sleep transition.
3601 			// Must re-scan assertions upon entering dark wake.
3602 
3603 			*cancel = true;
3604 			DLOG("cancel dark->sleep\n");
3605 		}
3606 		if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3607 			uint64_t now = mach_continuous_time();
3608 			if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3609 			    && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3610 				*cancel = true;
3611 				IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3612 			}
3613 		}
3614 	}
3615 }
3616 
3617 //******************************************************************************
3618 // systemDidNotSleep
3619 //
3620 // Work common to both canceled or aborted sleep.
3621 //******************************************************************************
3622 
3623 void
systemDidNotSleep(void)3624 IOPMrootDomain::systemDidNotSleep( void )
3625 {
3626 	// reset console lock state
3627 	thread_call_enter(updateConsoleUsersEntry);
3628 
3629 	if (idleSleepEnabled) {
3630 		if (!wrangler) {
3631 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3632 			startIdleSleepTimer(kIdleSleepRetryInterval);
3633 #else
3634 			startIdleSleepTimer(idleMilliSeconds);
3635 #endif
3636 		} else if (!userIsActive) {
3637 			// Manually start the idle sleep timer besides waiting for
3638 			// the user to become inactive.
3639 			startIdleSleepTimer(kIdleSleepRetryInterval);
3640 		}
3641 	}
3642 
3643 	preventTransitionToUserActive(false);
3644 	IOService::setAdvisoryTickleEnable( true );
3645 
3646 	// After idle revert and cancel, send a did-change message to powerd
3647 	// to balance the previous will-change message. Kernel clients do not
3648 	// need this since sleep cannot be canceled once they are notified.
3649 
3650 	if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3651 	    (_pendingCapability != _currentCapability) &&
3652 	    ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3653 		// Differs from a real capability gain change where notifyRef != 0,
3654 		// but it is zero here since no response is expected.
3655 
3656 		IOPMSystemCapabilityChangeParameters params;
3657 
3658 		bzero(&params, sizeof(params));
3659 		params.fromCapabilities = _pendingCapability;
3660 		params.toCapabilities = _currentCapability;
3661 		params.changeFlags = kIOPMSystemCapabilityDidChange;
3662 
3663 		DLOG("MESG cap %x->%x did change\n",
3664 		    params.fromCapabilities, params.toCapabilities);
3665 		messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3666 		    &params, sizeof(params));
3667 	}
3668 }
3669 
3670 //******************************************************************************
3671 // tellNoChangeDown
3672 //
3673 // Notify registered applications and kernel clients that we are not dropping
3674 // power.
3675 //
3676 // We override the superclass implementation so we can send a different message
3677 // type to the client or application being notified.
3678 //
3679 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3680 //******************************************************************************
3681 
3682 void
tellNoChangeDown(unsigned long stateNum)3683 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3684 {
3685 	DLOG("tellNoChangeDown %s->%s\n",
3686 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3687 
3688 	// Sleep canceled, clear the sleep trace point.
3689 	tracePoint(kIOPMTracePointSystemUp);
3690 
3691 	systemDidNotSleep();
3692 	return tellClients( kIOMessageSystemWillNotSleep );
3693 }
3694 
3695 //******************************************************************************
3696 // tellChangeUp
3697 //
3698 // Notify registered applications and kernel clients that we are raising power.
3699 //
3700 // We override the superclass implementation so we can send a different message
3701 // type to the client or application being notified.
3702 //******************************************************************************
3703 
3704 void
tellChangeUp(unsigned long stateNum)3705 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3706 {
3707 	DLOG("tellChangeUp %s->%s\n",
3708 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3709 
3710 	ignoreTellChangeDown = false;
3711 
3712 	if (stateNum == ON_STATE) {
3713 		// Direct callout into OSKext so it can disable kext unloads
3714 		// during sleep/wake to prevent deadlocks.
3715 		OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3716 
3717 		// Notify platform that sleep was cancelled or resumed.
3718 		getPlatform()->callPlatformFunction(
3719 			sleepMessagePEFunction.get(), false,
3720 			(void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3721 			NULL, NULL, NULL);
3722 
3723 		if (getPowerState() == ON_STATE) {
3724 			// Sleep was cancelled by idle cancel or revert
3725 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3726 				// rdar://problem/50363791
3727 				// If system is in dark wake and sleep is cancelled, do not
3728 				// send SystemWillPowerOn/HasPoweredOn messages to kernel
3729 				// priority clients. They haven't yet seen a SystemWillSleep
3730 				// message before the cancellation. So make sure the kernel
3731 				// client bit is cleared in _systemMessageClientMask before
3732 				// invoking the tellClients() below. This bit may have been
3733 				// set by handleOurPowerChangeStart() anticipating a successful
3734 				// sleep and setting the filter mask ahead of time allows the
3735 				// SystemWillSleep message to go through.
3736 				_systemMessageClientMask &= ~kSystemMessageClientKernel;
3737 			}
3738 
3739 			systemDidNotSleep();
3740 			tellClients( kIOMessageSystemWillPowerOn );
3741 		}
3742 
3743 		tracePoint( kIOPMTracePointWakeApplications );
3744 		tellClients( kIOMessageSystemHasPoweredOn );
3745 	} else if (stateNum == AOT_STATE) {
3746 		if (getPowerState() == AOT_STATE) {
3747 			// Sleep was cancelled by idle cancel or revert
3748 			startIdleSleepTimer(idleMilliSeconds);
3749 		}
3750 	}
3751 }
3752 
3753 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3754     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3755      ((params)->fromCapabilities & (flag)) && \
3756      (((params)->toCapabilities & (flag)) == 0))
3757 
3758 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3759     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3760      ((params)->toCapabilities & (flag)) && \
3761      (((params)->fromCapabilities & (flag)) == 0))
3762 
3763 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3764     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3765      ((params)->fromCapabilities & (flag)) && \
3766      (((params)->toCapabilities & (flag)) == 0))
3767 
3768 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3769     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3770      ((params)->toCapabilities & (flag)) && \
3771      (((params)->fromCapabilities & (flag)) == 0))
3772 
3773 //******************************************************************************
3774 // sysPowerDownHandler
3775 //
3776 // Perform a vfs sync before system sleep.
3777 //******************************************************************************
3778 
3779 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3780 IOPMrootDomain::sysPowerDownHandler(
3781 	void * target, void * refCon,
3782 	UInt32 messageType, IOService * service,
3783 	void * messageArgs, vm_size_t argSize )
3784 {
3785 	static UInt32 lastSystemMessageType = 0;
3786 	IOReturn    ret = 0;
3787 
3788 	DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3789 
3790 	// rdar://problem/50363791
3791 	// Sanity check to make sure the SystemWill/Has message types are
3792 	// received in the expected order for all kernel priority clients.
3793 	if (messageType == kIOMessageSystemWillSleep ||
3794 	    messageType == kIOMessageSystemWillPowerOn ||
3795 	    messageType == kIOMessageSystemHasPoweredOn) {
3796 		switch (messageType) {
3797 		case kIOMessageSystemWillPowerOn:
3798 			assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3799 			break;
3800 		case kIOMessageSystemHasPoweredOn:
3801 			assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3802 			break;
3803 		}
3804 
3805 		lastSystemMessageType = messageType;
3806 	}
3807 
3808 	if (!gRootDomain) {
3809 		return kIOReturnUnsupported;
3810 	}
3811 
3812 	if (messageType == kIOMessageSystemCapabilityChange) {
3813 		IOPMSystemCapabilityChangeParameters * params =
3814 		    (IOPMSystemCapabilityChangeParameters *) messageArgs;
3815 
3816 		// Interested applications have been notified of an impending power
3817 		// change and have acked (when applicable).
3818 		// This is our chance to save whatever state we can before powering
3819 		// down.
3820 		// We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3821 		// via callout
3822 
3823 		DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3824 		    params->fromCapabilities, params->toCapabilities,
3825 		    params->changeFlags);
3826 
3827 		if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3828 			// We will ack within 20 seconds
3829 			params->maxWaitForReply = 20 * 1000 * 1000;
3830 
3831 #if HIBERNATION
3832 			gRootDomain->evaluateSystemSleepPolicyEarly();
3833 
3834 			// add in time we could spend freeing pages
3835 			if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3836 				params->maxWaitForReply = kCapabilityClientMaxWait;
3837 			}
3838 			DLOG("sysPowerDownHandler max wait %d s\n",
3839 			    (int) (params->maxWaitForReply / 1000 / 1000));
3840 #endif
3841 
3842 			// Notify platform that sleep has begun, after the early
3843 			// sleep policy evaluation.
3844 			getPlatform()->callPlatformFunction(
3845 				sleepMessagePEFunction.get(), false,
3846 				(void *)(uintptr_t) kIOMessageSystemWillSleep,
3847 				NULL, NULL, NULL);
3848 
3849 			if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3850 				// Purposely delay the ack and hope that shutdown occurs quickly.
3851 				// Another option is not to schedule the thread and wait for
3852 				// ack timeout...
3853 				AbsoluteTime deadline;
3854 				clock_interval_to_deadline( 30, kSecondScale, &deadline );
3855 				thread_call_enter1_delayed(
3856 					gRootDomain->diskSyncCalloutEntry,
3857 					(thread_call_param_t)(uintptr_t) params->notifyRef,
3858 					deadline );
3859 			} else {
3860 				thread_call_enter1(
3861 					gRootDomain->diskSyncCalloutEntry,
3862 					(thread_call_param_t)(uintptr_t) params->notifyRef);
3863 			}
3864 		}
3865 #if HIBERNATION
3866 		else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
3867 			// We will ack within 110 seconds
3868 			params->maxWaitForReply = 110 * 1000 * 1000;
3869 
3870 			thread_call_enter1(
3871 				gRootDomain->diskSyncCalloutEntry,
3872 				(thread_call_param_t)(uintptr_t) params->notifyRef);
3873 		}
3874 #endif
3875 		ret = kIOReturnSuccess;
3876 	}
3877 
3878 	return ret;
3879 }
3880 
3881 //******************************************************************************
3882 // handleQueueSleepWakeUUID
3883 //
3884 // Called from IOPMrootDomain when we're initiating a sleep,
3885 // or indirectly from PM configd when PM decides to clear the UUID.
3886 // PM clears the UUID several minutes after successful wake from sleep,
3887 // so that we might associate App spindumps with the immediately previous
3888 // sleep/wake.
3889 //
3890 // @param   obj has a retain on it. We're responsible for releasing that retain.
3891 //******************************************************************************
3892 
3893 void
handleQueueSleepWakeUUID(OSObject * obj)3894 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
3895 {
3896 	OSSharedPtr<OSString>    str;
3897 
3898 	if (kOSBooleanFalse == obj) {
3899 		handlePublishSleepWakeUUID(false);
3900 	} else {
3901 		str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
3902 		if (str) {
3903 			// This branch caches the UUID for an upcoming sleep/wake
3904 			queuedSleepWakeUUIDString = str;
3905 			DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
3906 		}
3907 	}
3908 }
3909 //******************************************************************************
3910 // handlePublishSleepWakeUUID
3911 //
3912 // Called from IOPMrootDomain when we're initiating a sleep,
3913 // or indirectly from PM configd when PM decides to clear the UUID.
3914 // PM clears the UUID several minutes after successful wake from sleep,
3915 // so that we might associate App spindumps with the immediately previous
3916 // sleep/wake.
3917 //******************************************************************************
3918 
3919 void
handlePublishSleepWakeUUID(bool shouldPublish)3920 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
3921 {
3922 	ASSERT_GATED();
3923 
3924 	/*
3925 	 * Clear the current UUID
3926 	 */
3927 	if (gSleepWakeUUIDIsSet) {
3928 		DLOG("SleepWake UUID cleared\n");
3929 
3930 		gSleepWakeUUIDIsSet = false;
3931 
3932 		removeProperty(kIOPMSleepWakeUUIDKey);
3933 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
3934 	}
3935 
3936 	/*
3937 	 * Optionally, publish a new UUID
3938 	 */
3939 	if (queuedSleepWakeUUIDString && shouldPublish) {
3940 		OSSharedPtr<OSString> publishThisUUID;
3941 
3942 		publishThisUUID = queuedSleepWakeUUIDString;
3943 
3944 		if (publishThisUUID) {
3945 			setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
3946 		}
3947 
3948 		gSleepWakeUUIDIsSet = true;
3949 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
3950 
3951 		queuedSleepWakeUUIDString.reset();
3952 	}
3953 }
3954 
3955 //******************************************************************************
3956 // IOPMGetSleepWakeUUIDKey
3957 //
3958 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
3959 // To get the full key -- a C string -- the buffer must large enough for
3960 // the end-of-string character.
3961 // The key is expected to be an UUID string
3962 //******************************************************************************
3963 
3964 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)3965 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
3966 {
3967 	if (!gSleepWakeUUIDIsSet) {
3968 		return false;
3969 	}
3970 
3971 	if (buffer != NULL) {
3972 		OSSharedPtr<OSString> string =
3973 		    OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
3974 
3975 		if (!string) {
3976 			*buffer = '\0';
3977 		} else {
3978 			strlcpy(buffer, string->getCStringNoCopy(), buf_len);
3979 		}
3980 	}
3981 
3982 	return true;
3983 }
3984 
3985 //******************************************************************************
3986 // lowLatencyAudioNotify
3987 //
3988 // Used to send an update about low latency audio activity to interested
3989 // clients. To keep the overhead minimal the OSDictionary used here
3990 // is initialized at boot.
3991 //******************************************************************************
3992 
3993 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)3994 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
3995 {
3996 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
3997 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
3998 		lowLatencyAudioNotifyTimestampVal->setValue(time);
3999 		lowLatencyAudioNotifyStateVal->setValue(state);
4000 		setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4001 	} else {
4002 		DLOG("LowLatencyAudioNotify error\n");
4003 	}
4004 	return;
4005 }
4006 
4007 //******************************************************************************
4008 // IOPMrootDomainRTNotifier
4009 //
4010 // Used by performance controller to update the timestamp and state associated
4011 // with low latency audio activity in the system.
4012 //******************************************************************************
4013 
4014 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4015 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4016 {
4017 	gRootDomain->lowLatencyAudioNotify(time, state);
4018 	return;
4019 }
4020 
4021 //******************************************************************************
4022 // initializeBootSessionUUID
4023 //
4024 // Initialize the boot session uuid at boot up and sets it into registry.
4025 //******************************************************************************
4026 
4027 void
initializeBootSessionUUID(void)4028 IOPMrootDomain::initializeBootSessionUUID(void)
4029 {
4030 	uuid_t          new_uuid;
4031 	uuid_string_t   new_uuid_string;
4032 
4033 	uuid_generate(new_uuid);
4034 	uuid_unparse_upper(new_uuid, new_uuid_string);
4035 	memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4036 
4037 	setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4038 }
4039 
4040 //******************************************************************************
4041 // Root domain uses the private and tagged changePowerState methods for
4042 // tracking and logging purposes.
4043 //******************************************************************************
4044 
4045 #define REQUEST_TAG_TO_REASON(x)        ((uint16_t)x)
4046 
4047 static uint32_t
nextRequestTag(IOPMRequestTag tag)4048 nextRequestTag( IOPMRequestTag tag )
4049 {
4050 	static SInt16 msb16 = 1;
4051 	uint16_t id = OSAddAtomic16(1, &msb16);
4052 	return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4053 }
4054 
4055 // TODO: remove this shim function and exported symbol
4056 IOReturn
changePowerStateTo(unsigned long ordinal)4057 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4058 {
4059 	return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4060 }
4061 
4062 // TODO: remove this shim function and exported symbol
4063 IOReturn
changePowerStateToPriv(unsigned long ordinal)4064 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4065 {
4066 	return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4067 }
4068 
4069 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4070 IOPMrootDomain::changePowerStateWithOverrideTo(
4071 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4072 {
4073 	uint32_t tag = nextRequestTag(reason);
4074 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4075 
4076 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4077 		return kIOReturnUnsupported;
4078 	}
4079 
4080 	return super::changePowerStateWithOverrideTo(ordinal, tag);
4081 }
4082 
4083 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4084 IOPMrootDomain::changePowerStateWithTagTo(
4085 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4086 {
4087 	uint32_t tag = nextRequestTag(reason);
4088 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4089 
4090 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4091 		return kIOReturnUnsupported;
4092 	}
4093 
4094 	return super::changePowerStateWithTagTo(ordinal, tag);
4095 }
4096 
4097 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4098 IOPMrootDomain::changePowerStateWithTagToPriv(
4099 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4100 {
4101 	uint32_t tag = nextRequestTag(reason);
4102 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4103 
4104 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4105 		return kIOReturnUnsupported;
4106 	}
4107 
4108 	return super::changePowerStateWithTagToPriv(ordinal, tag);
4109 }
4110 
4111 //******************************************************************************
4112 // activity detect
4113 //
4114 //******************************************************************************
4115 
4116 bool
activitySinceSleep(void)4117 IOPMrootDomain::activitySinceSleep(void)
4118 {
4119 	return userActivityCount != userActivityAtSleep;
4120 }
4121 
4122 bool
abortHibernation(void)4123 IOPMrootDomain::abortHibernation(void)
4124 {
4125 #if __arm64__
4126 	// don't allow hibernation to be aborted on ARM due to user activity
4127 	// since once ApplePMGR decides we're hibernating, we can't turn back
4128 	// see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4129 	return false;
4130 #else
4131 	bool ret = activitySinceSleep();
4132 
4133 	if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4134 		DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4135 		hibernateAborted = true;
4136 	}
4137 	return ret;
4138 #endif
4139 }
4140 
4141 extern "C" int
hibernate_should_abort(void)4142 hibernate_should_abort(void)
4143 {
4144 	if (gRootDomain) {
4145 		return gRootDomain->abortHibernation();
4146 	} else {
4147 		return 0;
4148 	}
4149 }
4150 
4151 //******************************************************************************
4152 // willNotifyPowerChildren
4153 //
4154 // Called after all interested drivers have all acknowledged the power change,
4155 // but before any power children is informed. Dispatched though a thread call,
4156 // so it is safe to perform work that might block on a sleeping disk. PM state
4157 // machine (not thread) will block w/o timeout until this function returns.
4158 //******************************************************************************
4159 
4160 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4161 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4162 {
4163 	OSSharedPtr<OSDictionary> dict;
4164 	OSSharedPtr<OSNumber> secs;
4165 
4166 	if (SLEEP_STATE == newPowerState) {
4167 		notifierThread = current_thread();
4168 		if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4169 			AbsoluteTime deadline;
4170 
4171 			clock_interval_to_deadline(10, kSecondScale, &deadline);
4172 #if defined(XNU_TARGET_OS_OSX)
4173 			vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4174 #endif /* defined(XNU_TARGET_OS_OSX) */
4175 		}
4176 
4177 		_aotReadyToFullWake = false;
4178 #if 0
4179 		if (_aotLingerTime) {
4180 			uint64_t deadline;
4181 			IOLog("aot linger no return\n");
4182 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
4183 			clock_delay_until(deadline);
4184 		}
4185 #endif
4186 		if (!_aotMode) {
4187 			_aotTestTime = 0;
4188 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4189 			_aotLastWakeTime = 0;
4190 			if (_aotMetrics) {
4191 				bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4192 			}
4193 		} else if (!_aotNow && !_debugWakeSeconds) {
4194 			_aotNow            = true;
4195 			_aotPendingFlags   = 0;
4196 			_aotTasksSuspended = true;
4197 			_aotLastWakeTime   = 0;
4198 			bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4199 			if (kIOPMAOTModeCycle & _aotMode) {
4200 				clock_interval_to_absolutetime_interval(60, kSecondScale, &_aotTestInterval);
4201 				_aotTestTime = mach_continuous_time() + _aotTestInterval;
4202 				setWakeTime(_aotTestTime);
4203 			}
4204 			uint32_t lingerSecs;
4205 			if (!PE_parse_boot_argn("aotlinger", &lingerSecs, sizeof(lingerSecs))) {
4206 				lingerSecs = 0;
4207 			}
4208 			clock_interval_to_absolutetime_interval(lingerSecs, kSecondScale, &_aotLingerTime);
4209 			clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4210 			clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4211 		}
4212 
4213 #if HIBERNATION
4214 		IOHibernateSystemSleep();
4215 		IOHibernateIOKitSleep();
4216 #endif
4217 #if defined(__arm64__) && HIBERNATION
4218 		// On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4219 		// user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4220 		// alarms, which can mess with cycler tools.
4221 		if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4222 #else /* defined(__arm64__) && HIBERNATION */
4223 		// On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4224 		// RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4225 		if (gRootDomain->activitySinceSleep()) {
4226 #endif /* defined(__arm64__) && HIBERNATION */
4227 			dict = OSDictionary::withCapacity(1);
4228 			secs = OSNumber::withNumber(1, 32);
4229 
4230 			if (dict && secs) {
4231 				dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4232 				gRootDomain->setProperties(dict.get());
4233 				MSG("Reverting sleep with relative wake\n");
4234 			}
4235 		}
4236 
4237 		notifierThread = NULL;
4238 	}
4239 }
4240 
4241 //******************************************************************************
4242 // willTellSystemCapabilityDidChange
4243 //
4244 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4245 // domain is raising its power state, immediately after notifying interested
4246 // drivers and power children.
4247 //******************************************************************************
4248 
4249 void
4250 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4251 {
4252 	if ((_systemTransitionType == kSystemTransitionWake) &&
4253 	    !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4254 		// After powering up drivers, dark->full promotion on the current wake
4255 		// transition is no longer possible. That is because the next machine
4256 		// state will issue the system capability change messages.
4257 		// The darkWakePowerClamped flag may already be set if the system has
4258 		// at least one driver that was power clamped due to dark wake.
4259 		// This function sets the darkWakePowerClamped flag in case there
4260 		// is no power-clamped driver in the system.
4261 		//
4262 		// Last opportunity to exit dark wake using:
4263 		// requestFullWake( kFullWakeReasonLocalUser );
4264 
4265 		if (!darkWakePowerClamped) {
4266 			if (darkWakeLogClamp) {
4267 				AbsoluteTime    now;
4268 				uint64_t        nsec;
4269 
4270 				clock_get_uptime(&now);
4271 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4272 				absolutetime_to_nanoseconds(now, &nsec);
4273 				DLOG("dark wake promotion disabled at %u ms\n",
4274 				    ((int)((nsec) / NSEC_PER_MSEC)));
4275 			}
4276 			darkWakePowerClamped = true;
4277 		}
4278 	}
4279 }
4280 
4281 //******************************************************************************
4282 // sleepOnClamshellClosed
4283 //
4284 // contains the logic to determine if the system should sleep when the clamshell
4285 // is closed.
4286 //******************************************************************************
4287 
4288 bool
4289 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4290 {
4291 	if (!clamshellExists) {
4292 		return false;
4293 	}
4294 
4295 	DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4296 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4297 
4298 	return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4299 }
4300 
4301 bool
4302 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4303 {
4304 	// Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4305 	// closed && battery
4306 	if (!clamshellExists) {
4307 		return false;
4308 	}
4309 
4310 	DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4311 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4312 
4313 	return !acAdaptorConnected && !clamshellSleepDisableMask;
4314 }
4315 
4316 void
4317 IOPMrootDomain::sendClientClamshellNotification( void )
4318 {
4319 	/* Only broadcast clamshell alert if clamshell exists. */
4320 	if (!clamshellExists) {
4321 		return;
4322 	}
4323 
4324 	setProperty(kAppleClamshellStateKey,
4325 	    clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4326 
4327 	setProperty(kAppleClamshellCausesSleepKey,
4328 	    shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4329 
4330 	/* Argument to message is a bitfiel of
4331 	 *      ( kClamshellStateBit | kClamshellSleepBit )
4332 	 */
4333 	messageClients(kIOPMMessageClamshellStateChange,
4334 	    (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4335 	    | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4336 }
4337 
4338 //******************************************************************************
4339 // getSleepSupported
4340 //
4341 // Deprecated
4342 //******************************************************************************
4343 
4344 IOOptionBits
4345 IOPMrootDomain::getSleepSupported( void )
4346 {
4347 	return platformSleepSupport;
4348 }
4349 
4350 //******************************************************************************
4351 // setSleepSupported
4352 //
4353 // Deprecated
4354 //******************************************************************************
4355 
4356 void
4357 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4358 {
4359 	DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4360 	OSBitOrAtomic(flags, &platformSleepSupport);
4361 }
4362 
4363 //******************************************************************************
4364 // setClamShellSleepDisable
4365 //
4366 //******************************************************************************
4367 
4368 void
4369 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4370 {
4371 	uint32_t oldMask;
4372 
4373 	// User client calls this in non-gated context
4374 	if (gIOPMWorkLoop->inGate() == false) {
4375 		gIOPMWorkLoop->runAction(
4376 			OSMemberFunctionCast(IOWorkLoop::Action, this,
4377 			&IOPMrootDomain::setClamShellSleepDisable),
4378 			(OSObject *) this,
4379 			(void *) disable, (void *)(uintptr_t) bitmask);
4380 		return;
4381 	}
4382 
4383 	oldMask = clamshellSleepDisableMask;
4384 	if (disable) {
4385 		clamshellSleepDisableMask |= bitmask;
4386 	} else {
4387 		clamshellSleepDisableMask &= ~bitmask;
4388 	}
4389 	DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4390 
4391 	if (clamshellExists && clamshellClosed &&
4392 	    (clamshellSleepDisableMask != oldMask) &&
4393 	    (clamshellSleepDisableMask == 0)) {
4394 		handlePowerNotification(kLocalEvalClamshellCommand);
4395 	}
4396 }
4397 
4398 //******************************************************************************
4399 // wakeFromDoze
4400 //
4401 // Deprecated.
4402 //******************************************************************************
4403 
4404 void
4405 IOPMrootDomain::wakeFromDoze( void )
4406 {
4407 	// Preserve symbol for familes (IOUSBFamily and IOGraphics)
4408 }
4409 
4410 //******************************************************************************
4411 // recordRTCAlarm
4412 //
4413 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4414 // should be a dark wake or a full wake. Both Maintenance and SleepService
4415 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4416 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4417 // PMSettings are ignored.
4418 //
4419 // Caller serialized using settingsCtrlLock.
4420 //******************************************************************************
4421 
4422 void
4423 IOPMrootDomain::recordRTCAlarm(
4424 	const OSSymbol  *type,
4425 	OSObject        *object )
4426 {
4427 	uint32_t previousAlarmMask = _scheduledAlarmMask;
4428 
4429 	if (type == gIOPMSettingDebugWakeRelativeKey) {
4430 		OSNumber * n = OSDynamicCast(OSNumber, object);
4431 		if (n) {
4432 			// Debug wake has highest scheduling priority so it overrides any
4433 			// pre-existing alarm.
4434 			uint32_t debugSecs = n->unsigned32BitValue();
4435 			_nextScheduledAlarmType.reset(type, OSRetain);
4436 			_nextScheduledAlarmUTC = debugSecs;
4437 
4438 			_debugWakeSeconds = debugSecs;
4439 			OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4440 			DLOG("next alarm (%s) in %u secs\n",
4441 			    type->getCStringNoCopy(), debugSecs);
4442 		}
4443 	} else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4444 	    (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4445 	    (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4446 		OSData * data = OSDynamicCast(OSData, object);
4447 		if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4448 			const IOPMCalendarStruct * cs;
4449 			bool replaceNextAlarm = false;
4450 			clock_sec_t secs;
4451 
4452 			cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4453 			secs = IOPMConvertCalendarToSeconds(cs);
4454 			DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4455 
4456 			// Update the next scheduled alarm type
4457 			if ((_nextScheduledAlarmType == NULL) ||
4458 			    ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4459 			    (secs < _nextScheduledAlarmUTC))) {
4460 				replaceNextAlarm = true;
4461 			}
4462 
4463 			if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4464 				if (cs->year) {
4465 					_calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4466 					OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4467 				} else {
4468 					// TODO: can this else-block be removed?
4469 					_calendarWakeAlarmUTC = 0;
4470 					OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4471 				}
4472 			}
4473 			if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4474 				OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4475 			}
4476 			if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4477 				OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4478 			}
4479 
4480 			if (replaceNextAlarm) {
4481 				_nextScheduledAlarmType.reset(type, OSRetain);
4482 				_nextScheduledAlarmUTC = secs;
4483 				DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4484 			}
4485 		}
4486 	}
4487 
4488 	if (_scheduledAlarmMask != previousAlarmMask) {
4489 		DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4490 	}
4491 }
4492 
4493 // MARK: -
4494 // MARK: Features
4495 
4496 //******************************************************************************
4497 // publishFeature
4498 //
4499 // Adds a new feature to the supported features dictionary
4500 //******************************************************************************
4501 
4502 void
4503 IOPMrootDomain::publishFeature( const char * feature )
4504 {
4505 	publishFeature(feature, kRD_AllPowerSources, NULL);
4506 }
4507 
4508 //******************************************************************************
4509 // publishFeature (with supported power source specified)
4510 //
4511 // Adds a new feature to the supported features dictionary
4512 //******************************************************************************
4513 
4514 void
4515 IOPMrootDomain::publishFeature(
4516 	const char *feature,
4517 	uint32_t supportedWhere,
4518 	uint32_t *uniqueFeatureID)
4519 {
4520 	static uint16_t       next_feature_id = 500;
4521 
4522 	OSSharedPtr<OSNumber> new_feature_data;
4523 	OSNumber             *existing_feature = NULL;
4524 	OSArray              *existing_feature_arr_raw = NULL;
4525 	OSSharedPtr<OSArray>  existing_feature_arr;
4526 	OSObject             *osObj = NULL;
4527 	uint32_t              feature_value = 0;
4528 
4529 	supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4530 
4531 	if (!supportedWhere) {
4532 		// Feature isn't supported anywhere!
4533 		return;
4534 	}
4535 
4536 	if (next_feature_id > 5000) {
4537 		// Far, far too many features!
4538 		return;
4539 	}
4540 
4541 	if (featuresDictLock) {
4542 		IOLockLock(featuresDictLock);
4543 	}
4544 
4545 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4546 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4547 	OSSharedPtr<OSDictionary> features;
4548 
4549 	// Create new features dict if necessary
4550 	if (origFeatures) {
4551 		features = OSDictionary::withDictionary(origFeatures);
4552 	} else {
4553 		features = OSDictionary::withCapacity(1);
4554 	}
4555 
4556 	// Create OSNumber to track new feature
4557 
4558 	next_feature_id += 1;
4559 	if (uniqueFeatureID) {
4560 		// We don't really mind if the calling kext didn't give us a place
4561 		// to stash their unique id. Many kexts don't plan to unload, and thus
4562 		// have no need to remove themselves later.
4563 		*uniqueFeatureID = next_feature_id;
4564 	}
4565 
4566 	feature_value = (uint32_t)next_feature_id;
4567 	feature_value <<= 16;
4568 	feature_value += supportedWhere;
4569 
4570 	new_feature_data = OSNumber::withNumber(
4571 		(unsigned long long)feature_value, 32);
4572 
4573 	// Does features object already exist?
4574 	if ((osObj = features->getObject(feature))) {
4575 		if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4576 			// We need to create an OSArray to hold the now 2 elements.
4577 			existing_feature_arr = OSArray::withObjects(
4578 				(const OSObject **)&existing_feature, 1, 2);
4579 		} else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4580 			// Add object to existing array
4581 			existing_feature_arr = OSArray::withArray(
4582 				existing_feature_arr_raw,
4583 				existing_feature_arr_raw->getCount() + 1);
4584 		}
4585 
4586 		if (existing_feature_arr) {
4587 			existing_feature_arr->setObject(new_feature_data.get());
4588 			features->setObject(feature, existing_feature_arr.get());
4589 		}
4590 	} else {
4591 		// The easy case: no previously existing features listed. We simply
4592 		// set the OSNumber at key 'feature' and we're on our way.
4593 		features->setObject(feature, new_feature_data.get());
4594 	}
4595 
4596 	setProperty(kRootDomainSupportedFeatures, features.get());
4597 
4598 	if (featuresDictLock) {
4599 		IOLockUnlock(featuresDictLock);
4600 	}
4601 
4602 	// Notify EnergySaver and all those in user space so they might
4603 	// re-populate their feature specific UI
4604 	if (pmPowerStateQueue) {
4605 		pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4606 	}
4607 }
4608 
4609 //******************************************************************************
4610 // removePublishedFeature
4611 //
4612 // Removes previously published feature
4613 //******************************************************************************
4614 
4615 IOReturn
4616 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4617 {
4618 	IOReturn                ret = kIOReturnError;
4619 	uint32_t                feature_value = 0;
4620 	uint16_t                feature_id = 0;
4621 	bool                    madeAChange = false;
4622 
4623 	OSSymbol                *dictKey = NULL;
4624 	OSSharedPtr<OSCollectionIterator>    dictIterator;
4625 	OSArray                 *arrayMember  = NULL;
4626 	OSNumber                *numberMember = NULL;
4627 	OSObject                *osObj        = NULL;
4628 	OSNumber                *osNum        = NULL;
4629 	OSSharedPtr<OSArray>    arrayMemberCopy;
4630 
4631 	if (kBadPMFeatureID == removeFeatureID) {
4632 		return kIOReturnNotFound;
4633 	}
4634 
4635 	if (featuresDictLock) {
4636 		IOLockLock(featuresDictLock);
4637 	}
4638 
4639 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4640 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4641 	OSSharedPtr<OSDictionary> features;
4642 
4643 	if (origFeatures) {
4644 		// Any modifications to the dictionary are made to the copy to prevent
4645 		// races & crashes with userland clients. Dictionary updated
4646 		// automically later.
4647 		features = OSDictionary::withDictionary(origFeatures);
4648 	} else {
4649 		features = NULL;
4650 		ret = kIOReturnNotFound;
4651 		goto exit;
4652 	}
4653 
4654 	// We iterate 'features' dictionary looking for an entry tagged
4655 	// with 'removeFeatureID'. If found, we remove it from our tracking
4656 	// structures and notify the OS via a general interest message.
4657 
4658 	dictIterator = OSCollectionIterator::withCollection(features.get());
4659 	if (!dictIterator) {
4660 		goto exit;
4661 	}
4662 
4663 	while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4664 		osObj = features->getObject(dictKey);
4665 
4666 		// Each Feature is either tracked by an OSNumber
4667 		if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4668 			feature_value = numberMember->unsigned32BitValue();
4669 			feature_id = (uint16_t)(feature_value >> 16);
4670 
4671 			if (feature_id == (uint16_t)removeFeatureID) {
4672 				// Remove this node
4673 				features->removeObject(dictKey);
4674 				madeAChange = true;
4675 				break;
4676 			}
4677 
4678 			// Or tracked by an OSArray of OSNumbers
4679 		} else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4680 			unsigned int arrayCount = arrayMember->getCount();
4681 
4682 			for (unsigned int i = 0; i < arrayCount; i++) {
4683 				osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4684 				if (!osNum) {
4685 					continue;
4686 				}
4687 
4688 				feature_value = osNum->unsigned32BitValue();
4689 				feature_id = (uint16_t)(feature_value >> 16);
4690 
4691 				if (feature_id == (uint16_t)removeFeatureID) {
4692 					// Remove this node
4693 					if (1 == arrayCount) {
4694 						// If the array only contains one element, remove
4695 						// the whole thing.
4696 						features->removeObject(dictKey);
4697 					} else {
4698 						// Otherwise remove the element from a copy of the array.
4699 						arrayMemberCopy = OSArray::withArray(arrayMember);
4700 						if (arrayMemberCopy) {
4701 							arrayMemberCopy->removeObject(i);
4702 							features->setObject(dictKey, arrayMemberCopy.get());
4703 						}
4704 					}
4705 
4706 					madeAChange = true;
4707 					break;
4708 				}
4709 			}
4710 		}
4711 	}
4712 
4713 	if (madeAChange) {
4714 		ret = kIOReturnSuccess;
4715 
4716 		setProperty(kRootDomainSupportedFeatures, features.get());
4717 
4718 		// Notify EnergySaver and all those in user space so they might
4719 		// re-populate their feature specific UI
4720 		if (pmPowerStateQueue) {
4721 			pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4722 		}
4723 	} else {
4724 		ret = kIOReturnNotFound;
4725 	}
4726 
4727 exit:
4728 	if (featuresDictLock) {
4729 		IOLockUnlock(featuresDictLock);
4730 	}
4731 	return ret;
4732 }
4733 
4734 //******************************************************************************
4735 // publishPMSetting (private)
4736 //
4737 // Should only be called by PMSettingObject to publish a PM Setting as a
4738 // supported feature.
4739 //******************************************************************************
4740 
4741 void
4742 IOPMrootDomain::publishPMSetting(
4743 	const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4744 {
4745 	if (noPublishPMSettings &&
4746 	    (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4747 		// Setting found in noPublishPMSettings array
4748 		*featureID = kBadPMFeatureID;
4749 		return;
4750 	}
4751 
4752 	publishFeature(
4753 		feature->getCStringNoCopy(), where, featureID);
4754 }
4755 
4756 //******************************************************************************
4757 // setPMSetting (private)
4758 //
4759 // Internal helper to relay PM settings changes from user space to individual
4760 // drivers. Should be called only by IOPMrootDomain::setProperties.
4761 //******************************************************************************
4762 
4763 IOReturn
4764 IOPMrootDomain::setPMSetting(
4765 	const OSSymbol  *type,
4766 	OSObject        *object )
4767 {
4768 	PMSettingCallEntry  *entries = NULL;
4769 	OSSharedPtr<OSArray>    chosen;
4770 	const OSArray       *array;
4771 	PMSettingObject     *pmso;
4772 	thread_t            thisThread;
4773 	int                 i, j, count, capacity;
4774 	bool                ok = false;
4775 	IOReturn            ret;
4776 
4777 	if (NULL == type) {
4778 		return kIOReturnBadArgument;
4779 	}
4780 
4781 	PMSETTING_LOCK();
4782 
4783 	// Update settings dict so changes are visible from copyPMSetting().
4784 	fPMSettingsDict->setObject(type, object);
4785 
4786 	// Prep all PMSetting objects with the given 'type' for callout.
4787 	array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4788 	if (!array || ((capacity = array->getCount()) == 0)) {
4789 		goto unlock_exit;
4790 	}
4791 
4792 	// Array to retain PMSetting objects targeted for callout.
4793 	chosen = OSArray::withCapacity(capacity);
4794 	if (!chosen) {
4795 		goto unlock_exit; // error
4796 	}
4797 	entries = IONew(PMSettingCallEntry, capacity);
4798 	if (!entries) {
4799 		goto unlock_exit; // error
4800 	}
4801 	memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4802 
4803 	thisThread = current_thread();
4804 
4805 	for (i = 0, j = 0; i < capacity; i++) {
4806 		pmso = (PMSettingObject *) array->getObject(i);
4807 		if (pmso->disabled) {
4808 			continue;
4809 		}
4810 		entries[j].thread = thisThread;
4811 		queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4812 		chosen->setObject(pmso);
4813 		j++;
4814 	}
4815 	count = j;
4816 	if (!count) {
4817 		goto unlock_exit;
4818 	}
4819 
4820 	PMSETTING_UNLOCK();
4821 
4822 	// Call each pmso in the chosen array.
4823 	for (i = 0; i < count; i++) {
4824 		pmso = (PMSettingObject *) chosen->getObject(i);
4825 		ret = pmso->dispatchPMSetting(type, object);
4826 		if (ret == kIOReturnSuccess) {
4827 			// At least one setting handler was successful
4828 			ok = true;
4829 #if DEVELOPMENT || DEBUG
4830 		} else {
4831 			// Log the handler and kext that failed
4832 			OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
4833 			if (kextName) {
4834 				DLOG("PMSetting(%s) error 0x%x from %s\n",
4835 				    type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
4836 			}
4837 #endif
4838 		}
4839 	}
4840 
4841 	PMSETTING_LOCK();
4842 	for (i = 0; i < count; i++) {
4843 		pmso = (PMSettingObject *) chosen->getObject(i);
4844 		queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
4845 		if (pmso->waitThread) {
4846 			PMSETTING_WAKEUP(pmso);
4847 		}
4848 	}
4849 
4850 	if (ok) {
4851 		recordRTCAlarm(type, object);
4852 	}
4853 unlock_exit:
4854 	PMSETTING_UNLOCK();
4855 
4856 	if (entries) {
4857 		IODelete(entries, PMSettingCallEntry, capacity);
4858 	}
4859 
4860 	return kIOReturnSuccess;
4861 }
4862 
4863 //******************************************************************************
4864 // copyPMSetting (public)
4865 //
4866 // Allows kexts to safely read setting values, without being subscribed to
4867 // notifications.
4868 //******************************************************************************
4869 
4870 OSSharedPtr<OSObject>
4871 IOPMrootDomain::copyPMSetting(
4872 	OSSymbol *whichSetting)
4873 {
4874 	OSSharedPtr<OSObject> obj;
4875 
4876 	if (!whichSetting) {
4877 		return NULL;
4878 	}
4879 
4880 	PMSETTING_LOCK();
4881 	obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
4882 	PMSETTING_UNLOCK();
4883 
4884 	return obj;
4885 }
4886 
4887 //******************************************************************************
4888 // registerPMSettingController (public)
4889 //
4890 // direct wrapper to registerPMSettingController with uint32_t power source arg
4891 //******************************************************************************
4892 
4893 IOReturn
4894 IOPMrootDomain::registerPMSettingController(
4895 	const OSSymbol *                settings[],
4896 	IOPMSettingControllerCallback   func,
4897 	OSObject                        *target,
4898 	uintptr_t                       refcon,
4899 	OSObject                        **handle)
4900 {
4901 	return registerPMSettingController(
4902 		settings,
4903 		(kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
4904 		func, target, refcon, handle);
4905 }
4906 
4907 //******************************************************************************
4908 // registerPMSettingController (public)
4909 //
4910 // Kexts may register for notifications when a particular setting is changed.
4911 // A list of settings is available in IOPM.h.
4912 // Arguments:
4913 //  * settings - An OSArray containing OSSymbols. Caller should populate this
4914 //          array with a list of settings caller wants notifications from.
4915 //  * func - A C function callback of the type IOPMSettingControllerCallback
4916 //  * target - caller may provide an OSObject *, which PM will pass as an
4917 //          target to calls to "func"
4918 //  * refcon - caller may provide an void *, which PM will pass as an
4919 //          argument to calls to "func"
4920 //  * handle - This is a return argument. We will populate this pointer upon
4921 //          call success. Hold onto this and pass this argument to
4922 //          IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
4923 // Returns:
4924 //      kIOReturnSuccess on success
4925 //******************************************************************************
4926 
4927 IOReturn
4928 IOPMrootDomain::registerPMSettingController(
4929 	const OSSymbol *                settings[],
4930 	uint32_t                        supportedPowerSources,
4931 	IOPMSettingControllerCallback   func,
4932 	OSObject                        *target,
4933 	uintptr_t                       refcon,
4934 	OSObject                        **handle)
4935 {
4936 	PMSettingObject *pmso = NULL;
4937 	OSObject        *pmsh = NULL;
4938 	int             i;
4939 
4940 	if (NULL == settings ||
4941 	    NULL == func ||
4942 	    NULL == handle) {
4943 		return kIOReturnBadArgument;
4944 	}
4945 
4946 	pmso = PMSettingObject::pmSettingObject(
4947 		(IOPMrootDomain *) this, func, target,
4948 		refcon, supportedPowerSources, settings, &pmsh);
4949 
4950 	if (!pmso) {
4951 		*handle = NULL;
4952 		return kIOReturnInternalError;
4953 	}
4954 
4955 	PMSETTING_LOCK();
4956 	for (i = 0; settings[i]; i++) {
4957 		OSSharedPtr<OSArray> newList;
4958 		OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
4959 		if (!list) {
4960 			// New array of callbacks for this setting
4961 			newList = OSArray::withCapacity(1);
4962 			settingsCallbacks->setObject(settings[i], newList.get());
4963 			list = newList.get();
4964 		}
4965 
4966 		// Add caller to the callback list
4967 		list->setObject(pmso);
4968 	}
4969 	PMSETTING_UNLOCK();
4970 
4971 	// Return handle to the caller, the setting object is private.
4972 	*handle = pmsh;
4973 
4974 	return kIOReturnSuccess;
4975 }
4976 
4977 //******************************************************************************
4978 // deregisterPMSettingObject (private)
4979 //
4980 // Only called from PMSettingObject.
4981 //******************************************************************************
4982 
4983 void
4984 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
4985 {
4986 	thread_t                thisThread = current_thread();
4987 	PMSettingCallEntry      *callEntry;
4988 	OSSharedPtr<OSCollectionIterator>    iter;
4989 	OSSymbol                *sym;
4990 	OSArray                 *array;
4991 	int                     index;
4992 	bool                    wait;
4993 
4994 	PMSETTING_LOCK();
4995 
4996 	pmso->disabled = true;
4997 
4998 	// Wait for all callout threads to finish.
4999 	do {
5000 		wait = false;
5001 		queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5002 		{
5003 			if (callEntry->thread != thisThread) {
5004 				wait = true;
5005 				break;
5006 			}
5007 		}
5008 		if (wait) {
5009 			assert(NULL == pmso->waitThread);
5010 			pmso->waitThread = thisThread;
5011 			PMSETTING_WAIT(pmso);
5012 			pmso->waitThread = NULL;
5013 		}
5014 	} while (wait);
5015 
5016 	// Search each PM settings array in the kernel.
5017 	iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5018 	if (iter) {
5019 		while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5020 			array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5021 			index = array->getNextIndexOfObject(pmso, 0);
5022 			if (-1 != index) {
5023 				array->removeObject(index);
5024 			}
5025 		}
5026 	}
5027 
5028 	PMSETTING_UNLOCK();
5029 
5030 	pmso->release();
5031 }
5032 
5033 //******************************************************************************
5034 // informCPUStateChange
5035 //
5036 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5037 // running on battery, with the lid closed, etc.
5038 //
5039 // informCPUStateChange is a no-op on non x86 systems
5040 // only x86 has explicit support in the IntelCPUPowerManagement kext
5041 //******************************************************************************
5042 
5043 void
5044 IOPMrootDomain::informCPUStateChange(
5045 	uint32_t type,
5046 	uint32_t value )
5047 {
5048 #if defined(__i386__) || defined(__x86_64__)
5049 
5050 	pmioctlVariableInfo_t varInfoStruct;
5051 	int                 pmCPUret = 0;
5052 	const char          *varNameStr = NULL;
5053 	int32_t             *varIndex   = NULL;
5054 
5055 	if (kInformAC == type) {
5056 		varNameStr = kIOPMRootDomainBatPowerCString;
5057 		varIndex = &idxPMCPULimitedPower;
5058 	} else if (kInformLid == type) {
5059 		varNameStr = kIOPMRootDomainLidCloseCString;
5060 		varIndex = &idxPMCPUClamshell;
5061 	} else {
5062 		return;
5063 	}
5064 
5065 	// Set the new value!
5066 	// pmCPUControl will assign us a new ID if one doesn't exist yet
5067 	bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5068 	varInfoStruct.varID         = *varIndex;
5069 	varInfoStruct.varType       = vBool;
5070 	varInfoStruct.varInitValue  = value;
5071 	varInfoStruct.varCurValue   = value;
5072 	strlcpy((char *)varInfoStruct.varName,
5073 	    (const char *)varNameStr,
5074 	    sizeof(varInfoStruct.varName));
5075 
5076 	// Set!
5077 	pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5078 
5079 	// pmCPU only assigns numerical id's when a new varName is specified
5080 	if ((0 == pmCPUret)
5081 	    && (*varIndex == kCPUUnknownIndex)) {
5082 		// pmCPUControl has assigned us a new variable ID.
5083 		// Let's re-read the structure we just SET to learn that ID.
5084 		pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5085 
5086 		if (0 == pmCPUret) {
5087 			// Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5088 			*varIndex = varInfoStruct.varID;
5089 		}
5090 	}
5091 
5092 	return;
5093 
5094 #endif /* __i386__ || __x86_64__ */
5095 }
5096 
5097 // MARK: -
5098 // MARK: Deep Sleep Policy
5099 
5100 #if HIBERNATION
5101 
5102 //******************************************************************************
5103 // evaluateSystemSleepPolicy
5104 //******************************************************************************
5105 
5106 #define kIOPlatformSystemSleepPolicyKey     "IOPlatformSystemSleepPolicy"
5107 
5108 // Sleep flags
5109 enum {
5110 	kIOPMSleepFlagHibernate         = 0x00000001,
5111 	kIOPMSleepFlagSleepTimerEnable  = 0x00000002
5112 };
5113 
5114 struct IOPMSystemSleepPolicyEntry {
5115 	uint32_t    factorMask;
5116 	uint32_t    factorBits;
5117 	uint32_t    sleepFlags;
5118 	uint32_t    wakeEvents;
5119 } __attribute__((packed));
5120 
5121 struct IOPMSystemSleepPolicyTable {
5122 	uint32_t    signature;
5123 	uint16_t    version;
5124 	uint16_t    entryCount;
5125 	IOPMSystemSleepPolicyEntry  entries[];
5126 } __attribute__((packed));
5127 
5128 enum {
5129 	kIOPMSleepAttributeHibernateSetup   = 0x00000001,
5130 	kIOPMSleepAttributeHibernateSleep   = 0x00000002
5131 };
5132 
5133 static uint32_t
5134 getSleepTypeAttributes( uint32_t sleepType )
5135 {
5136 	static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5137 	{
5138 		/* invalid   */ 0,
5139 		/* abort     */ 0,
5140 		/* normal    */ 0,
5141 		/* safesleep */ kIOPMSleepAttributeHibernateSetup,
5142 		/* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5143 		/* standby   */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5144 		/* poweroff  */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5145 		/* deepidle  */ 0
5146 	};
5147 
5148 	if (sleepType >= kIOPMSleepTypeLast) {
5149 		return 0;
5150 	}
5151 
5152 	return sleepTypeAttributes[sleepType];
5153 }
5154 
5155 bool
5156 IOPMrootDomain::evaluateSystemSleepPolicy(
5157 	IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5158 {
5159 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5160 
5161 	static const IONamedValue factorValues[] = {
5162 		SLEEP_FACTOR( SleepTimerWake ),
5163 		SLEEP_FACTOR( LidOpen ),
5164 		SLEEP_FACTOR( ACPower ),
5165 		SLEEP_FACTOR( BatteryLow ),
5166 		SLEEP_FACTOR( StandbyNoDelay ),
5167 		SLEEP_FACTOR( StandbyForced ),
5168 		SLEEP_FACTOR( StandbyDisabled ),
5169 		SLEEP_FACTOR( USBExternalDevice ),
5170 		SLEEP_FACTOR( BluetoothHIDDevice ),
5171 		SLEEP_FACTOR( ExternalMediaMounted ),
5172 		SLEEP_FACTOR( ThunderboltDevice ),
5173 		SLEEP_FACTOR( RTCAlarmScheduled ),
5174 		SLEEP_FACTOR( MagicPacketWakeEnabled ),
5175 		SLEEP_FACTOR( HibernateForced ),
5176 		SLEEP_FACTOR( AutoPowerOffDisabled ),
5177 		SLEEP_FACTOR( AutoPowerOffForced ),
5178 		SLEEP_FACTOR( ExternalDisplay ),
5179 		SLEEP_FACTOR( NetworkKeepAliveActive ),
5180 		SLEEP_FACTOR( LocalUserActivity ),
5181 		SLEEP_FACTOR( HibernateFailed ),
5182 		SLEEP_FACTOR( ThermalWarning ),
5183 		SLEEP_FACTOR( DisplayCaptured ),
5184 		{ 0, NULL }
5185 	};
5186 
5187 	const IOPMSystemSleepPolicyTable * pt;
5188 	OSSharedPtr<OSObject>  prop;
5189 	OSData *    policyData;
5190 	uint64_t    currentFactors = 0;
5191 	char        currentFactorsBuf[512];
5192 	uint32_t    standbyDelay   = 0;
5193 	uint32_t    powerOffDelay  = 0;
5194 	uint32_t    powerOffTimer  = 0;
5195 	uint32_t    standbyTimer  = 0;
5196 	uint32_t    mismatch;
5197 	bool        standbyEnabled;
5198 	bool        powerOffEnabled;
5199 	bool        found = false;
5200 
5201 	// Get platform's sleep policy table
5202 	if (!gSleepPolicyHandler) {
5203 		prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5204 		if (!prop) {
5205 			goto done;
5206 		}
5207 	}
5208 
5209 	// Fetch additional settings
5210 	standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5211 	    && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5212 	powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5213 	    && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5214 	if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5215 		powerOffTimer = powerOffDelay;
5216 	}
5217 	if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5218 		standbyTimer = standbyDelay;
5219 	}
5220 
5221 	DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5222 	    sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5223 	    powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5224 
5225 	currentFactorsBuf[0] = 0;
5226 	// pmset level overrides
5227 	if ((*hibMode & kIOHibernateModeOn) == 0) {
5228 		if (!gSleepPolicyHandler) {
5229 			standbyEnabled  = false;
5230 			powerOffEnabled = false;
5231 		}
5232 	} else if (!(*hibMode & kIOHibernateModeSleep)) {
5233 		// Force hibernate (i.e. mode 25)
5234 		// If standby is enabled, force standy.
5235 		// If poweroff is enabled, force poweroff.
5236 		if (standbyEnabled) {
5237 			currentFactors |= kIOPMSleepFactorStandbyForced;
5238 		} else if (powerOffEnabled) {
5239 			currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5240 		} else {
5241 			currentFactors |= kIOPMSleepFactorHibernateForced;
5242 		}
5243 	}
5244 
5245 	// Current factors based on environment and assertions
5246 	if (sleepTimerMaintenance) {
5247 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5248 	}
5249 	if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5250 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5251 	}
5252 	if (!clamshellClosed) {
5253 		currentFactors |= kIOPMSleepFactorLidOpen;
5254 	}
5255 	if (acAdaptorConnected) {
5256 		currentFactors |= kIOPMSleepFactorACPower;
5257 	}
5258 	if (lowBatteryCondition) {
5259 		hibernateMode = 0;
5260 		getSleepOption(kIOHibernateModeKey, &hibernateMode);
5261 		if ((hibernateMode & kIOHibernateModeOn) == 0) {
5262 			DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5263 		} else {
5264 			currentFactors |= kIOPMSleepFactorBatteryLow;
5265 		}
5266 	}
5267 	if (!standbyDelay || !standbyTimer) {
5268 		currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5269 	}
5270 	if (standbyNixed || !standbyEnabled) {
5271 		currentFactors |= kIOPMSleepFactorStandbyDisabled;
5272 	}
5273 	if (resetTimers) {
5274 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5275 		currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5276 	}
5277 	if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5278 	    kIOPMDriverAssertionLevelOff) {
5279 		currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5280 	}
5281 	if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5282 	    kIOPMDriverAssertionLevelOff) {
5283 		currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5284 	}
5285 	if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5286 	    kIOPMDriverAssertionLevelOff) {
5287 		currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5288 	}
5289 	if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5290 	    kIOPMDriverAssertionLevelOff) {
5291 		currentFactors |= kIOPMSleepFactorThunderboltDevice;
5292 	}
5293 	if (_scheduledAlarmMask != 0) {
5294 		currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5295 	}
5296 	if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5297 	    kIOPMDriverAssertionLevelOff) {
5298 		currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5299 	}
5300 #define TCPKEEPALIVE 1
5301 #if TCPKEEPALIVE
5302 	if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5303 	    kIOPMDriverAssertionLevelOff) {
5304 		currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5305 	}
5306 #endif
5307 	if (!powerOffEnabled) {
5308 		currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5309 	}
5310 	if (desktopMode) {
5311 		currentFactors |= kIOPMSleepFactorExternalDisplay;
5312 	}
5313 	if (userWasActive) {
5314 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5315 	}
5316 	if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5317 		currentFactors |= kIOPMSleepFactorHibernateFailed;
5318 	}
5319 	if (thermalWarningState) {
5320 		currentFactors |= kIOPMSleepFactorThermalWarning;
5321 	}
5322 
5323 	for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5324 		uint32_t factor = 1 << factorBit;
5325 		if (factor & currentFactors) {
5326 			strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5327 			strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5328 		}
5329 	}
5330 	DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5331 
5332 	if (gSleepPolicyHandler) {
5333 		uint32_t    savedHibernateMode;
5334 		IOReturn    result;
5335 
5336 		if (!gSleepPolicyVars) {
5337 			gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5338 		}
5339 		gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5340 		gSleepPolicyVars->version   = kIOPMSystemSleepPolicyVersion;
5341 		gSleepPolicyVars->currentCapability = _currentCapability;
5342 		gSleepPolicyVars->highestCapability = _highestCapability;
5343 		gSleepPolicyVars->sleepFactors      = currentFactors;
5344 		gSleepPolicyVars->sleepReason       = lastSleepReason;
5345 		gSleepPolicyVars->sleepPhase        = sleepPhase;
5346 		gSleepPolicyVars->standbyDelay      = standbyDelay;
5347 		gSleepPolicyVars->standbyTimer      = standbyTimer;
5348 		gSleepPolicyVars->poweroffDelay     = powerOffDelay;
5349 		gSleepPolicyVars->scheduledAlarms   = _scheduledAlarmMask | _userScheduledAlarmMask;
5350 		gSleepPolicyVars->poweroffTimer     = powerOffTimer;
5351 
5352 		if (kIOPMSleepPhase0 == sleepPhase) {
5353 			// preserve hibernateMode
5354 			savedHibernateMode = gSleepPolicyVars->hibernateMode;
5355 			gSleepPolicyVars->hibernateMode = *hibMode;
5356 		} else if (kIOPMSleepPhase1 == sleepPhase) {
5357 			// use original hibernateMode for phase2
5358 			gSleepPolicyVars->hibernateMode = *hibMode;
5359 		}
5360 
5361 		result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5362 
5363 		if (kIOPMSleepPhase0 == sleepPhase) {
5364 			// restore hibernateMode
5365 			gSleepPolicyVars->hibernateMode = savedHibernateMode;
5366 		}
5367 
5368 		if ((result != kIOReturnSuccess) ||
5369 		    (kIOPMSleepTypeInvalid == params->sleepType) ||
5370 		    (params->sleepType >= kIOPMSleepTypeLast) ||
5371 		    (kIOPMSystemSleepParametersVersion != params->version)) {
5372 			MSG("sleep policy handler error\n");
5373 			goto done;
5374 		}
5375 
5376 		if ((getSleepTypeAttributes(params->sleepType) &
5377 		    kIOPMSleepAttributeHibernateSetup) &&
5378 		    ((*hibMode & kIOHibernateModeOn) == 0)) {
5379 			*hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5380 		}
5381 
5382 		DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5383 		    params->version, params->sleepType, params->sleepFlags,
5384 		    params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5385 		found = true;
5386 		goto done;
5387 	}
5388 
5389 	// Policy table is meaningless without standby enabled
5390 	if (!standbyEnabled) {
5391 		goto done;
5392 	}
5393 
5394 	// Validate the sleep policy table
5395 	policyData = OSDynamicCast(OSData, prop.get());
5396 	if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5397 		goto done;
5398 	}
5399 
5400 	pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5401 	if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5402 	    (pt->version != 1) || (0 == pt->entryCount)) {
5403 		goto done;
5404 	}
5405 
5406 	if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5407 	    (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5408 		goto done;
5409 	}
5410 
5411 	for (uint32_t i = 0; i < pt->entryCount; i++) {
5412 		const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5413 		mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5414 
5415 		DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5416 		    entry->factorMask, entry->factorBits,
5417 		    entry->sleepFlags, entry->wakeEvents, mismatch);
5418 		if (mismatch) {
5419 			continue;
5420 		}
5421 
5422 		DLOG("^ found match\n");
5423 		found = true;
5424 
5425 		params->version = kIOPMSystemSleepParametersVersion;
5426 		params->reserved1 = 1;
5427 		if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5428 			params->sleepType = kIOPMSleepTypeStandby;
5429 		} else {
5430 			params->sleepType = kIOPMSleepTypeNormalSleep;
5431 		}
5432 
5433 		params->ecWakeEvents = entry->wakeEvents;
5434 		if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5435 			if (kIOPMSleepPhase2 == sleepPhase) {
5436 				clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5437 
5438 				if (!_standbyTimerResetSeconds ||
5439 				    (now_secs <= _standbyTimerResetSeconds)) {
5440 					// Reset standby timer adjustment
5441 					_standbyTimerResetSeconds = now_secs;
5442 					DLOG("standby delay %u, reset %u\n",
5443 					    standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5444 				} else if (standbyDelay) {
5445 					// Shorten the standby delay timer
5446 					clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5447 					if (standbyDelay > elapsed) {
5448 						standbyDelay -= elapsed;
5449 					} else {
5450 						standbyDelay = 1; // must be > 0
5451 					}
5452 					DLOG("standby delay %u, elapsed %u\n",
5453 					    standbyDelay, (uint32_t) elapsed);
5454 				}
5455 			}
5456 			params->ecWakeTimer = standbyDelay;
5457 		} else if (kIOPMSleepPhase2 == sleepPhase) {
5458 			// A sleep that does not enable the sleep timer will reset
5459 			// the standby delay adjustment.
5460 			_standbyTimerResetSeconds = 0;
5461 		}
5462 		break;
5463 	}
5464 
5465 done:
5466 	return found;
5467 }
5468 
5469 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5470 
5471 void
5472 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5473 {
5474 	// Evaluate early (priority interest phase), before drivers sleep.
5475 
5476 	DLOG("%s\n", __FUNCTION__);
5477 	removeProperty(kIOPMSystemSleepParametersKey);
5478 
5479 	// Full wake resets the standby timer delay adjustment
5480 	if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5481 		_standbyTimerResetSeconds = 0;
5482 	}
5483 
5484 	hibernateDisabled = false;
5485 	hibernateMode = 0;
5486 	getSleepOption(kIOHibernateModeKey, &hibernateMode);
5487 
5488 	// Save for late evaluation if sleep is aborted
5489 	bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5490 
5491 	if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5492 	    &hibernateMode)) {
5493 		if (!hibernateRetry &&
5494 		    ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5495 		    kIOPMSleepAttributeHibernateSetup) == 0)) {
5496 			// skip hibernate setup
5497 			hibernateDisabled = true;
5498 		}
5499 	}
5500 
5501 	// Publish IOPMSystemSleepType
5502 	uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5503 	if (sleepType == kIOPMSleepTypeInvalid) {
5504 		// no sleep policy
5505 		sleepType = kIOPMSleepTypeNormalSleep;
5506 		if (hibernateMode & kIOHibernateModeOn) {
5507 			sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5508 			    kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5509 		}
5510 	} else if ((sleepType == kIOPMSleepTypeStandby) &&
5511 	    (gEarlySystemSleepParams.ecPoweroffTimer)) {
5512 		// report the lowest possible sleep state
5513 		sleepType = kIOPMSleepTypePowerOff;
5514 	}
5515 
5516 	setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5517 }
5518 
5519 void
5520 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5521 {
5522 	IOPMSystemSleepParameters   params;
5523 	OSSharedPtr<OSData>         paramsData;
5524 	bool                        wakeNow;
5525 	// Evaluate sleep policy after sleeping drivers but before platform sleep.
5526 
5527 	DLOG("%s\n", __FUNCTION__);
5528 
5529 	bzero(&params, sizeof(params));
5530 	wakeNow = false;
5531 	if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
5532 		if ((kIOPMSleepTypeStandby == params.sleepType)
5533 		    && gIOHibernateStandbyDisabled && gSleepPolicyVars
5534 		    && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5535 		    & gSleepPolicyVars->sleepFactors))) {
5536 			standbyNixed = true;
5537 			wakeNow = true;
5538 		}
5539 		if (wakeNow
5540 		    || ((hibernateDisabled || hibernateAborted) &&
5541 		    (getSleepTypeAttributes(params.sleepType) &
5542 		    kIOPMSleepAttributeHibernateSetup))) {
5543 			// Final evaluation picked a state requiring hibernation,
5544 			// but hibernate isn't going to proceed. Arm a short sleep using
5545 			// the early non-hibernate sleep parameters.
5546 			bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
5547 			params.sleepType = kIOPMSleepTypeAbortedSleep;
5548 			params.ecWakeTimer = 1;
5549 			if (standbyNixed) {
5550 				resetTimers = true;
5551 			} else {
5552 				// Set hibernateRetry flag to force hibernate setup on the
5553 				// next sleep.
5554 				hibernateRetry = true;
5555 			}
5556 			DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5557 			    params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5558 		} else {
5559 			hibernateRetry = false;
5560 		}
5561 
5562 		if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5563 			resetTimers = false;
5564 		}
5565 
5566 		paramsData = OSData::withValue(params);
5567 		if (paramsData) {
5568 			setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5569 		}
5570 
5571 		if (getSleepTypeAttributes(params.sleepType) &
5572 		    kIOPMSleepAttributeHibernateSleep) {
5573 			// Disable sleep to force hibernation
5574 			gIOHibernateMode &= ~kIOHibernateModeSleep;
5575 		}
5576 	}
5577 }
5578 
5579 bool
5580 IOPMrootDomain::getHibernateSettings(
5581 	uint32_t *  hibernateModePtr,
5582 	uint32_t *  hibernateFreeRatio,
5583 	uint32_t *  hibernateFreeTime )
5584 {
5585 	// Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5586 	// has updated the hibernateDisabled flag.
5587 
5588 	bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5589 	getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5590 	getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5591 	if (hibernateDisabled) {
5592 		*hibernateModePtr = 0;
5593 	} else if (gSleepPolicyHandler) {
5594 		*hibernateModePtr = hibernateMode;
5595 	}
5596 	DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5597 	return ok;
5598 }
5599 
5600 bool
5601 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5602 {
5603 	OSSharedPtr<OSObject>       optionsProp;
5604 	OSDictionary *              optionsDict;
5605 	OSSharedPtr<OSObject>       obj;
5606 	OSNumber *                  num;
5607 	bool                        ok = false;
5608 
5609 	optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5610 	optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5611 
5612 	if (optionsDict) {
5613 		obj.reset(optionsDict->getObject(key), OSRetain);
5614 	}
5615 	if (!obj) {
5616 		obj = copyProperty(key);
5617 	}
5618 	if (obj) {
5619 		if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5620 			*option = num->unsigned32BitValue();
5621 			ok = true;
5622 		} else if (OSDynamicCast(OSBoolean, obj.get())) {
5623 			*option = (obj == kOSBooleanTrue) ? 1 : 0;
5624 			ok = true;
5625 		}
5626 	}
5627 
5628 	return ok;
5629 }
5630 #endif /* HIBERNATION */
5631 
5632 IOReturn
5633 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5634 {
5635 #if HIBERNATION
5636 	IOPMSystemSleepParameters   params;
5637 	uint32_t                    hibMode = 0;
5638 	bool                        ok;
5639 
5640 	if (gIOPMWorkLoop->inGate() == false) {
5641 		IOReturn ret = gIOPMWorkLoop->runAction(
5642 			OSMemberFunctionCast(IOWorkLoop::Action, this,
5643 			&IOPMrootDomain::getSystemSleepType),
5644 			(OSObject *) this,
5645 			(void *) sleepType, (void *) standbyTimer);
5646 		return ret;
5647 	}
5648 
5649 	getSleepOption(kIOHibernateModeKey, &hibMode);
5650 	bzero(&params, sizeof(params));
5651 
5652 	ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
5653 	if (ok) {
5654 		*sleepType = params.sleepType;
5655 		if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5656 		    !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5657 			DLOG("Standby delay is not set\n");
5658 			*standbyTimer = 0;
5659 		}
5660 		return kIOReturnSuccess;
5661 	}
5662 #endif
5663 
5664 	return kIOReturnUnsupported;
5665 }
5666 
5667 // MARK: -
5668 // MARK: Shutdown and Restart
5669 
5670 //******************************************************************************
5671 // handlePlatformHaltRestart
5672 //
5673 //******************************************************************************
5674 
5675 // Phases while performing shutdown/restart
5676 typedef enum {
5677 	kNotifyDone                 = 0x00,
5678 	kNotifyPriorityClients      = 0x10,
5679 	kNotifyPowerPlaneDrivers    = 0x20,
5680 	kNotifyHaltRestartAction    = 0x30,
5681 	kQuiescePM                  = 0x40,
5682 } shutdownPhase_t;
5683 
5684 
5685 struct HaltRestartApplierContext {
5686 	IOPMrootDomain *    RootDomain;
5687 	unsigned long       PowerState;
5688 	IOPMPowerFlags      PowerFlags;
5689 	UInt32              MessageType;
5690 	UInt32              Counter;
5691 	const char *        LogString;
5692 	shutdownPhase_t     phase;
5693 
5694 	IOServiceInterestHandler    handler;
5695 } gHaltRestartCtx;
5696 
5697 const char *
5698 shutdownPhase2String(shutdownPhase_t phase)
5699 {
5700 	switch (phase) {
5701 	case kNotifyDone:
5702 		return "Notifications completed";
5703 	case kNotifyPriorityClients:
5704 		return "Notifying priority clients";
5705 	case kNotifyPowerPlaneDrivers:
5706 		return "Notifying power plane drivers";
5707 	case kNotifyHaltRestartAction:
5708 		return "Notifying HaltRestart action handlers";
5709 	case kQuiescePM:
5710 		return "Quiescing PM";
5711 	default:
5712 		return "Unknown";
5713 	}
5714 }
5715 
5716 static void
5717 platformHaltRestartApplier( OSObject * object, void * context )
5718 {
5719 	IOPowerStateChangeNotification  notify;
5720 	HaltRestartApplierContext *     ctx;
5721 	AbsoluteTime                    startTime, elapsedTime;
5722 	uint32_t                        deltaTime;
5723 
5724 	ctx = (HaltRestartApplierContext *) context;
5725 
5726 	_IOServiceInterestNotifier * notifier;
5727 	notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5728 	memset(&notify, 0, sizeof(notify));
5729 	notify.powerRef    = (void *)(uintptr_t)ctx->Counter;
5730 	notify.returnValue = 0;
5731 	notify.stateNumber = ctx->PowerState;
5732 	notify.stateFlags  = ctx->PowerFlags;
5733 
5734 	if (notifier) {
5735 		ctx->handler = notifier->handler;
5736 	}
5737 
5738 	clock_get_uptime(&startTime);
5739 	ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
5740 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5741 
5742 	if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5743 		LOG("%s handler %p took %u ms\n",
5744 		    ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5745 		halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5746 	}
5747 
5748 	ctx->handler = NULL;
5749 	ctx->Counter++;
5750 }
5751 
5752 static void
5753 quiescePowerTreeCallback( void * target, void * param )
5754 {
5755 	IOLockLock(gPMHaltLock);
5756 	gPMQuiesced = true;
5757 	thread_wakeup(param);
5758 	IOLockUnlock(gPMHaltLock);
5759 }
5760 
5761 void
5762 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5763 {
5764 	AbsoluteTime                startTime, elapsedTime;
5765 	uint32_t                    deltaTime;
5766 	bool                        nvramSync = false;
5767 
5768 	memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5769 	gHaltRestartCtx.RootDomain = this;
5770 
5771 	clock_get_uptime(&startTime);
5772 	switch (pe_type) {
5773 	case kPEHaltCPU:
5774 	case kPEUPSDelayHaltCPU:
5775 		gHaltRestartCtx.PowerState  = OFF_STATE;
5776 		gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5777 		gHaltRestartCtx.LogString   = "PowerOff";
5778 		nvramSync = true;
5779 		break;
5780 
5781 	case kPERestartCPU:
5782 		gHaltRestartCtx.PowerState  = RESTART_STATE;
5783 		gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5784 		gHaltRestartCtx.LogString   = "Restart";
5785 		nvramSync = true;
5786 		break;
5787 
5788 	case kPEPagingOff:
5789 		gHaltRestartCtx.PowerState  = ON_STATE;
5790 		gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5791 		gHaltRestartCtx.LogString   = "PagingOff";
5792 		IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5793 #if HIBERNATION
5794 		IOHibernateSystemRestart();
5795 #endif
5796 		break;
5797 
5798 	default:
5799 		return;
5800 	}
5801 
5802 	if (nvramSync) {
5803 		PESyncNVRAM();
5804 	}
5805 
5806 	gHaltRestartCtx.phase = kNotifyPriorityClients;
5807 	// Notify legacy clients
5808 	applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5809 
5810 	// For normal shutdown, turn off File Server Mode.
5811 	if (kPEHaltCPU == pe_type) {
5812 		OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5813 		OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5814 		if (setting && num) {
5815 			setPMSetting(setting.get(), num.get());
5816 		}
5817 	}
5818 
5819 	if (kPEPagingOff != pe_type) {
5820 		gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5821 		// Notify in power tree order
5822 		notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5823 	}
5824 
5825 	gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5826 #if defined(XNU_TARGET_OS_OSX)
5827 	IOCPURunPlatformHaltRestartActions(pe_type);
5828 #else /* !defined(XNU_TARGET_OS_OSX) */
5829 	if (kPEPagingOff != pe_type) {
5830 		IOCPURunPlatformHaltRestartActions(pe_type);
5831 	}
5832 #endif /* !defined(XNU_TARGET_OS_OSX) */
5833 
5834 	// Wait for PM to quiesce
5835 	if ((kPEPagingOff != pe_type) && gPMHaltLock) {
5836 		gHaltRestartCtx.phase = kQuiescePM;
5837 		AbsoluteTime quiesceTime = mach_absolute_time();
5838 
5839 		IOLockLock(gPMHaltLock);
5840 		gPMQuiesced = false;
5841 		if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
5842 		    kIOReturnSuccess) {
5843 			while (!gPMQuiesced) {
5844 				IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
5845 			}
5846 		}
5847 		IOLockUnlock(gPMHaltLock);
5848 		deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
5849 		DLOG("PM quiesce took %u ms\n", deltaTime);
5850 		halt_log_enter("Quiesce", NULL, elapsedTime);
5851 	}
5852 	gHaltRestartCtx.phase = kNotifyDone;
5853 
5854 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5855 	LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5856 
5857 	halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
5858 
5859 	deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5860 	LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
5861 
5862 	if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
5863 		printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
5864 	}
5865 
5866 	checkShutdownTimeout();
5867 }
5868 
5869 bool
5870 IOPMrootDomain::checkShutdownTimeout()
5871 {
5872 	AbsoluteTime   elapsedTime;
5873 	uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
5874 
5875 	if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
5876 		return true;
5877 	}
5878 	return false;
5879 }
5880 
5881 void
5882 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
5883 {
5884 	if (gHaltLog) {
5885 		if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
5886 			halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
5887 		}
5888 		panic("%s timed out in phase '%s'. Total %d ms:%s",
5889 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
5890 	} else {
5891 		panic("%s timed out in phase \'%s\'. Total %d ms",
5892 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
5893 	}
5894 }
5895 
5896 //******************************************************************************
5897 // shutdownSystem
5898 //
5899 //******************************************************************************
5900 
5901 IOReturn
5902 IOPMrootDomain::shutdownSystem( void )
5903 {
5904 	return kIOReturnUnsupported;
5905 }
5906 
5907 //******************************************************************************
5908 // restartSystem
5909 //
5910 //******************************************************************************
5911 
5912 IOReturn
5913 IOPMrootDomain::restartSystem( void )
5914 {
5915 	return kIOReturnUnsupported;
5916 }
5917 
5918 // MARK: -
5919 // MARK: System Capability
5920 
5921 //******************************************************************************
5922 // tagPowerPlaneService
5923 //
5924 // Running on PM work loop thread.
5925 //******************************************************************************
5926 
5927 void
5928 IOPMrootDomain::tagPowerPlaneService(
5929 	IOService *         service,
5930 	IOPMActions *       actions,
5931 	IOPMPowerStateIndex maxPowerState )
5932 {
5933 	uint32_t    flags = 0;
5934 
5935 	memset(actions, 0, sizeof(*actions));
5936 	actions->target = this;
5937 
5938 	if (service == this) {
5939 		actions->actionPowerChangeStart =
5940 		    OSMemberFunctionCast(
5941 			IOPMActionPowerChangeStart, this,
5942 			&IOPMrootDomain::handleOurPowerChangeStart);
5943 
5944 		actions->actionPowerChangeDone =
5945 		    OSMemberFunctionCast(
5946 			IOPMActionPowerChangeDone, this,
5947 			&IOPMrootDomain::handleOurPowerChangeDone);
5948 
5949 		actions->actionPowerChangeOverride =
5950 		    OSMemberFunctionCast(
5951 			IOPMActionPowerChangeOverride, this,
5952 			&IOPMrootDomain::overrideOurPowerChange);
5953 		return;
5954 	}
5955 
5956 #if DISPLAY_WRANGLER_PRESENT
5957 	if (NULL != service->metaCast("IODisplayWrangler")) {
5958 		// XXX should this really retain?
5959 		wrangler.reset(service, OSRetain);
5960 		wrangler->registerInterest(gIOGeneralInterest,
5961 		    &displayWranglerNotification, this, NULL);
5962 
5963 		// found the display wrangler, check for any display assertions already created
5964 		if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
5965 			DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
5966 			wrangler->setIgnoreIdleTimer( true );
5967 		}
5968 		flags |= kPMActionsFlagIsDisplayWrangler;
5969 	}
5970 #endif /* DISPLAY_WRANGLER_PRESENT */
5971 
5972 	if (service->propertyExists("IOPMStrictTreeOrder")) {
5973 		flags |= kPMActionsFlagIsGraphicsDriver;
5974 	}
5975 	if (service->propertyExists("IOPMUnattendedWakePowerState")) {
5976 		flags |= kPMActionsFlagIsAudioDriver;
5977 	}
5978 
5979 	// Find the power connection object that is a child of the PCI host
5980 	// bridge, and has a graphics/audio device attached below. Mark the
5981 	// power branch for delayed child notifications.
5982 
5983 	if (flags) {
5984 		IORegistryEntry * child  = service;
5985 		IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
5986 
5987 		while (child != this) {
5988 			if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
5989 				// Skip delaying notifications and clamping power on external graphics and audio devices.
5990 				DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
5991 				flags = 0;
5992 				break;
5993 			}
5994 			if ((parent == pciHostBridgeDriver) ||
5995 			    (parent == this)) {
5996 				if (OSDynamicCast(IOPowerConnection, child)) {
5997 					IOPowerConnection * conn = (IOPowerConnection *) child;
5998 					conn->delayChildNotification = true;
5999 					DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6000 				}
6001 				break;
6002 			}
6003 			child = parent;
6004 			parent = child->getParentEntry(gIOPowerPlane);
6005 		}
6006 	}
6007 
6008 	OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6009 	if (prop) {
6010 		OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6011 		if (num) {
6012 			actions->darkWakePowerState = num->unsigned32BitValue();
6013 			if (actions->darkWakePowerState < maxPowerState) {
6014 				flags |= kPMActionsFlagHasDarkWakePowerState;
6015 			}
6016 		}
6017 	}
6018 
6019 
6020 	if (flags) {
6021 		DLOG("%s tag flags %x\n", service->getName(), flags);
6022 		actions->flags |= flags;
6023 		actions->actionPowerChangeOverride =
6024 		    OSMemberFunctionCast(
6025 			IOPMActionPowerChangeOverride, this,
6026 			&IOPMrootDomain::overridePowerChangeForService);
6027 
6028 		if (flags & kPMActionsFlagIsDisplayWrangler) {
6029 			actions->actionActivityTickle =
6030 			    OSMemberFunctionCast(
6031 				IOPMActionActivityTickle, this,
6032 				&IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6033 
6034 			actions->actionUpdatePowerClient =
6035 			    OSMemberFunctionCast(
6036 				IOPMActionUpdatePowerClient, this,
6037 				&IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6038 		}
6039 		return;
6040 	}
6041 
6042 	// Locate the first PCI host bridge for PMTrace.
6043 	if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6044 		IOService * provider = service->getProvider();
6045 		if (OSDynamicCast(IOPlatformDevice, provider) &&
6046 		    provider->inPlane(gIODTPlane)) {
6047 			pciHostBridgeDevice.reset(provider, OSNoRetain);
6048 			pciHostBridgeDriver.reset(service, OSNoRetain);
6049 			DLOG("PMTrace found PCI host bridge %s->%s\n",
6050 			    provider->getName(), service->getName());
6051 		}
6052 	}
6053 
6054 	// Tag top-level PCI devices. The order of PMinit() call does not
6055 	// change across boots and is used as the PCI bit number.
6056 	if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6057 		// Would prefer to check built-in property, but tagPowerPlaneService()
6058 		// is called before pciDevice->registerService().
6059 		IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6060 		if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6061 			int bit = pmTracer->recordTopLevelPCIDevice( service );
6062 			if (bit >= 0) {
6063 				// Save the assigned bit for fast lookup.
6064 				actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6065 
6066 				actions->actionPowerChangeStart =
6067 				    OSMemberFunctionCast(
6068 					IOPMActionPowerChangeStart, this,
6069 					&IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6070 
6071 				actions->actionPowerChangeDone =
6072 				    OSMemberFunctionCast(
6073 					IOPMActionPowerChangeDone, this,
6074 					&IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6075 			}
6076 		}
6077 	}
6078 }
6079 
6080 //******************************************************************************
6081 // PM actions for root domain
6082 //******************************************************************************
6083 
6084 void
6085 IOPMrootDomain::overrideOurPowerChange(
6086 	IOService *             service,
6087 	IOPMActions *           actions,
6088 	const IOPMRequest *     request,
6089 	IOPMPowerStateIndex *   inOutPowerState,
6090 	IOPMPowerChangeFlags *  inOutChangeFlags )
6091 {
6092 	uint32_t changeFlags = *inOutChangeFlags;
6093 	uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6094 	uint32_t currentPowerState = (uint32_t) getPowerState();
6095 
6096 	if (request->getTag() == 0) {
6097 		// Set a tag for any request that originates from IOServicePM
6098 		(const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6099 	}
6100 
6101 	DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6102 	    getPowerStateString(currentPowerState),
6103 	    getPowerStateString(desiredPowerState),
6104 	    _currentCapability, changeFlags,
6105 	    request->getTag());
6106 
6107 
6108 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6109 	/*
6110 	 * ASBM send lowBattery notifications every 1 second until the device
6111 	 * enters hibernation. This queues up multiple sleep requests.
6112 	 * After the device wakes from hibernation, none of these previously
6113 	 * queued sleep requests are valid.
6114 	 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6115 	 * and is cleared at the very last point in sleep.
6116 	 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6117 	 * lowBatteryCondition is invalid
6118 	 */
6119 	if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6120 		if (!lowBatteryCondition) {
6121 			DLOG("Duplicate lowBattery sleep");
6122 			*inOutChangeFlags |= kIOPMNotDone;
6123 			return;
6124 		}
6125 	}
6126 #endif
6127 
6128 	if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6129 		// Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6130 		*inOutChangeFlags |= kIOPMNotDone;
6131 		return;
6132 	}
6133 
6134 	if (changeFlags & kIOPMParentInitiated) {
6135 		// Root parent is permanently pegged at max power,
6136 		// a parent initiated power change is unexpected.
6137 		*inOutChangeFlags |= kIOPMNotDone;
6138 		return;
6139 	}
6140 
6141 	if (desiredPowerState < currentPowerState) {
6142 		if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6143 			// Root domain is dropping power state from ON->SLEEP.
6144 			// If system is in full wake, first enter dark wake by
6145 			// converting the power drop to a capability change.
6146 			// Once in dark wake, transition to sleep state ASAP.
6147 
6148 			darkWakeToSleepASAP = true;
6149 
6150 			// Drop graphics and audio capability
6151 			_desiredCapability &= ~(
6152 				kIOPMSystemCapabilityGraphics |
6153 				kIOPMSystemCapabilityAudio);
6154 
6155 			// Convert to capability change (ON->ON)
6156 			*inOutPowerState = getRUN_STATE();
6157 			*inOutChangeFlags |= kIOPMSynchronize;
6158 
6159 			// Revert device desire from SLEEP to ON
6160 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6161 		} else {
6162 			// System is already in dark wake, ok to drop power state.
6163 			// Broadcast root power down to entire tree.
6164 			*inOutChangeFlags |= kIOPMRootChangeDown;
6165 		}
6166 	} else if (desiredPowerState > currentPowerState) {
6167 		if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6168 			// Broadcast power up when waking from sleep, but not for the
6169 			// initial power change at boot by checking for cpu capability.
6170 			*inOutChangeFlags |= kIOPMRootChangeUp;
6171 		}
6172 	}
6173 }
6174 
6175 void
6176 IOPMrootDomain::handleOurPowerChangeStart(
6177 	IOService *             service,
6178 	IOPMActions *           actions,
6179 	const IOPMRequest *     request,
6180 	IOPMPowerStateIndex     newPowerState,
6181 	IOPMPowerChangeFlags *  inOutChangeFlags )
6182 {
6183 	IOPMRequestTag requestTag = request->getTag();
6184 	IOPMRequestTag sleepReason;
6185 
6186 	uint32_t changeFlags        = *inOutChangeFlags;
6187 	uint32_t currentPowerState  = (uint32_t) getPowerState();
6188 	bool     publishSleepReason = false;
6189 
6190 	// Check if request has a valid sleep reason
6191 	sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6192 	if (sleepReason < kIOPMSleepReasonClamshell) {
6193 		sleepReason = kIOPMSleepReasonIdle;
6194 	}
6195 
6196 	_systemTransitionType    = kSystemTransitionNone;
6197 	_systemMessageClientMask = 0;
6198 	capabilityLoss           = false;
6199 	toldPowerdCapWillChange  = false;
6200 
6201 	// Emergency notifications may arrive after the initial sleep request
6202 	// has been queued. Override the sleep reason so powerd and others can
6203 	// treat this as an emergency sleep.
6204 	if (lowBatteryCondition) {
6205 		sleepReason = kIOPMSleepReasonLowPower;
6206 	} else if (thermalEmergencyState) {
6207 		sleepReason = kIOPMSleepReasonThermalEmergency;
6208 	}
6209 
6210 	// 1. Explicit capability change.
6211 	if (changeFlags & kIOPMSynchronize) {
6212 		if (newPowerState == ON_STATE) {
6213 			if (changeFlags & kIOPMSyncNoChildNotify) {
6214 				_systemTransitionType = kSystemTransitionNewCapClient;
6215 			} else {
6216 				_systemTransitionType = kSystemTransitionCapability;
6217 			}
6218 		}
6219 	}
6220 	// 2. Going to sleep (cancellation still possible).
6221 	else if (newPowerState < currentPowerState) {
6222 		_systemTransitionType = kSystemTransitionSleep;
6223 	}
6224 	// 3. Woke from (idle or demand) sleep.
6225 	else if (!systemBooting &&
6226 	    (changeFlags & kIOPMSelfInitiated) &&
6227 	    (newPowerState > currentPowerState)) {
6228 		_systemTransitionType = kSystemTransitionWake;
6229 		_desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6230 
6231 		// Early exit from dark wake to full (e.g. LID open)
6232 		if (kFullWakeReasonNone != fullWakeReason) {
6233 			_desiredCapability |= (
6234 				kIOPMSystemCapabilityGraphics |
6235 				kIOPMSystemCapabilityAudio);
6236 
6237 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6238 			if (fullWakeReason == kFullWakeReasonLocalUser) {
6239 				darkWakeExit = true;
6240 				darkWakeToSleepASAP = false;
6241 				setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6242 				    kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6243 			}
6244 #endif
6245 		}
6246 #if HIBERNATION
6247 		IOHibernateSetWakeCapabilities(_desiredCapability);
6248 #endif
6249 	}
6250 
6251 	// Update pending wake capability at the beginning of every
6252 	// state transition (including synchronize). This will become
6253 	// the current capability at the end of the transition.
6254 
6255 	if (kSystemTransitionSleep == _systemTransitionType) {
6256 		_pendingCapability = 0;
6257 		capabilityLoss = true;
6258 	} else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6259 		_pendingCapability = _desiredCapability |
6260 		    kIOPMSystemCapabilityCPU |
6261 		    kIOPMSystemCapabilityNetwork;
6262 
6263 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6264 			_pendingCapability |= kIOPMSystemCapabilityAudio;
6265 		}
6266 
6267 		if ((kSystemTransitionCapability == _systemTransitionType) &&
6268 		    (_pendingCapability == _currentCapability)) {
6269 			// Cancel the PM state change.
6270 			_systemTransitionType = kSystemTransitionNone;
6271 			*inOutChangeFlags |= kIOPMNotDone;
6272 		}
6273 		if (__builtin_popcount(_pendingCapability) <
6274 		    __builtin_popcount(_currentCapability)) {
6275 			capabilityLoss = true;
6276 		}
6277 	}
6278 
6279 	// 1. Capability change.
6280 	if (kSystemTransitionCapability == _systemTransitionType) {
6281 		// Dark to Full transition.
6282 		if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6283 			tracePoint( kIOPMTracePointDarkWakeExit );
6284 
6285 #if defined(XNU_TARGET_OS_OSX)
6286 			// rdar://problem/65627936
6287 			// When a dark->full wake promotion is scheduled before an ON->SLEEP
6288 			// power state drop, invalidate any request to drop power state already
6289 			// in the queue, including the override variant, unless full wake cannot
6290 			// be sustained. Any power state drop queued after this SustainFullWake
6291 			// request will not be affected.
6292 			if (checkSystemCanSustainFullWake()) {
6293 				changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6294 			}
6295 #endif
6296 
6297 			willEnterFullWake();
6298 		}
6299 
6300 		// Full to Dark transition.
6301 		if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6302 			// Clear previous stats
6303 			IOLockLock(pmStatsLock);
6304 			if (pmStatsAppResponses) {
6305 				pmStatsAppResponses = OSArray::withCapacity(5);
6306 			}
6307 			IOLockUnlock(pmStatsLock);
6308 
6309 			tracePoint( kIOPMTracePointDarkWakeEntry );
6310 			*inOutChangeFlags |= kIOPMSyncTellPowerDown;
6311 			_systemMessageClientMask = kSystemMessageClientPowerd |
6312 			    kSystemMessageClientLegacyApp;
6313 
6314 			// rdar://15971327
6315 			// Prevent user active transitions before notifying clients
6316 			// that system will sleep.
6317 			preventTransitionToUserActive(true);
6318 
6319 			IOService::setAdvisoryTickleEnable( false );
6320 
6321 			// Publish the sleep reason for full to dark wake
6322 			publishSleepReason = true;
6323 			lastSleepReason = fullToDarkReason = sleepReason;
6324 
6325 			// Publish a UUID for the Sleep --> Wake cycle
6326 			handlePublishSleepWakeUUID(true);
6327 			if (sleepDelaysReport) {
6328 				clock_get_uptime(&ts_sleepStart);
6329 				DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6330 			}
6331 
6332 			darkWakeExit = false;
6333 		}
6334 	}
6335 	// 2. System sleep.
6336 	else if (kSystemTransitionSleep == _systemTransitionType) {
6337 		// Beginning of a system sleep transition.
6338 		// Cancellation is still possible.
6339 		tracePoint( kIOPMTracePointSleepStarted );
6340 
6341 		_systemMessageClientMask = kSystemMessageClientAll;
6342 		if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6343 			_systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6344 		}
6345 		if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6346 			// Kernel priority clients are only notified on the initial
6347 			// transition to full wake, so don't notify them unless system
6348 			// has gained graphics capability since the last system wake.
6349 			_systemMessageClientMask &= ~kSystemMessageClientKernel;
6350 		} else {
6351 			// System was in full wake, but the downwards power transition is driven
6352 			// by a request that originates from IOServicePM, so it isn't tagged with
6353 			// a valid system sleep reason.
6354 			if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6355 				// Publish the same reason for full to dark
6356 				sleepReason = fullToDarkReason;
6357 			}
6358 		}
6359 #if HIBERNATION
6360 		gIOHibernateState = 0;
6361 #endif
6362 
6363 		// Record the reason for dark wake back to sleep
6364 		// System may not have ever achieved full wake
6365 
6366 		publishSleepReason = true;
6367 		lastSleepReason = sleepReason;
6368 		if (sleepDelaysReport) {
6369 			clock_get_uptime(&ts_sleepStart);
6370 			DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6371 		}
6372 	}
6373 	// 3. System wake.
6374 	else if (kSystemTransitionWake == _systemTransitionType) {
6375 		tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6376 		// Clear stats about sleep
6377 
6378 		if (AOT_STATE == newPowerState) {
6379 			_pendingCapability = 0;
6380 		}
6381 
6382 		if (AOT_STATE == currentPowerState) {
6383 			// Wake events are no longer accepted after waking to AOT_STATE.
6384 			// Re-enable wake event acceptance to append wake events claimed
6385 			// during the AOT to ON_STATE transition.
6386 			acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6387 		}
6388 
6389 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6390 			willEnterFullWake();
6391 		}
6392 	}
6393 
6394 	// The only location where the sleep reason is published. At this point
6395 	// sleep can still be cancelled, but sleep reason should be published
6396 	// early for logging purposes.
6397 
6398 	if (publishSleepReason) {
6399 		static const char * IOPMSleepReasons[] =
6400 		{
6401 			kIOPMClamshellSleepKey,
6402 			kIOPMPowerButtonSleepKey,
6403 			kIOPMSoftwareSleepKey,
6404 			kIOPMOSSwitchHibernationKey,
6405 			kIOPMIdleSleepKey,
6406 			kIOPMLowPowerSleepKey,
6407 			kIOPMThermalEmergencySleepKey,
6408 			kIOPMMaintenanceSleepKey,
6409 			kIOPMSleepServiceExitKey,
6410 			kIOPMDarkWakeThermalEmergencyKey,
6411 			kIOPMNotificationWakeExitKey
6412 		};
6413 
6414 		// Record sleep cause in IORegistry
6415 		uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6416 		if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6417 			DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6418 #if DEVELOPMENT || DEBUG
6419 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6420 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6421 			    "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6422 			    );
6423 #endif /* DEVELOPMENT || DEBUG */
6424 			setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6425 		}
6426 	}
6427 
6428 	if ((kSystemTransitionNone != _systemTransitionType) &&
6429 	    (kSystemTransitionNewCapClient != _systemTransitionType)) {
6430 		_systemStateGeneration++;
6431 		systemDarkWake = false;
6432 
6433 		DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6434 		    getPowerStateString(currentPowerState),
6435 		    getPowerStateString((uint32_t) newPowerState),
6436 		    _currentCapability, _pendingCapability,
6437 		    *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6438 		    requestTag);
6439 #if DEVELOPMENT || DEBUG
6440 		if (currentPowerState != (uint32_t) newPowerState) {
6441 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6442 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6443 			    "Start Power State Trans.",
6444 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6445 			    getPowerStateString(currentPowerState),
6446 			    getPowerStateString((uint32_t) newPowerState),
6447 			    _currentCapability,
6448 			    _pendingCapability,
6449 			    *inOutChangeFlags,
6450 			    _systemStateGeneration,
6451 			    _systemMessageClientMask,
6452 			    requestTag
6453 			    );
6454 		}
6455 #endif /* DEVELOPMENT || DEBUG */
6456 	}
6457 
6458 	if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6459 		panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6460 	}
6461 	if (_aotNow && (ON_STATE == newPowerState)) {
6462 		WAKEEVENT_LOCK();
6463 		aotShouldExit(false, true);
6464 		WAKEEVENT_UNLOCK();
6465 		aotExit(false);
6466 	}
6467 }
6468 
6469 void
6470 IOPMrootDomain::handleOurPowerChangeDone(
6471 	IOService *             service,
6472 	IOPMActions *           actions,
6473 	const IOPMRequest *     request,
6474 	IOPMPowerStateIndex     oldPowerState,
6475 	IOPMPowerChangeFlags    changeFlags )
6476 {
6477 	if (kSystemTransitionNewCapClient == _systemTransitionType) {
6478 		_systemTransitionType = kSystemTransitionNone;
6479 		return;
6480 	}
6481 
6482 	if (_systemTransitionType != kSystemTransitionNone) {
6483 		uint32_t currentPowerState = (uint32_t) getPowerState();
6484 
6485 		if (changeFlags & kIOPMNotDone) {
6486 			// Power down was cancelled or vetoed.
6487 			_pendingCapability = _currentCapability;
6488 			lastSleepReason = 0;
6489 
6490 			// When sleep is cancelled or reverted, don't report
6491 			// the target (lower) power state as the previous state.
6492 			oldPowerState = currentPowerState;
6493 
6494 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6495 			    CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6496 #if defined(XNU_TARGET_OS_OSX)
6497 				pmPowerStateQueue->submitPowerEvent(
6498 					kPowerEventPolicyStimulus,
6499 					(void *) kStimulusDarkWakeReentry,
6500 					_systemStateGeneration );
6501 #else /* !defined(XNU_TARGET_OS_OSX) */
6502 				// On embedded, there are no factors that can prolong a
6503 				// "darkWake" when a power down is vetoed. We need to
6504 				// promote to "fullWake" at least once so that factors
6505 				// that prevent idle sleep can assert themselves if required
6506 				pmPowerStateQueue->submitPowerEvent(
6507 					kPowerEventPolicyStimulus,
6508 					(void *) kStimulusDarkWakeActivityTickle);
6509 #endif /* !defined(XNU_TARGET_OS_OSX) */
6510 			}
6511 
6512 			// Revert device desire to max.
6513 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6514 		} else {
6515 			// Send message on dark wake to full wake promotion.
6516 			// tellChangeUp() handles the normal SLEEP->ON case.
6517 
6518 			if (kSystemTransitionCapability == _systemTransitionType) {
6519 				if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6520 					lastSleepReason = 0; // stop logging wrangler tickles
6521 					tellClients(kIOMessageSystemHasPoweredOn);
6522 				}
6523 				if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6524 					// Going dark, reset full wake state
6525 					// userIsActive will be cleared by wrangler powering down
6526 					fullWakeReason = kFullWakeReasonNone;
6527 
6528 					if (ts_sleepStart) {
6529 						clock_get_uptime(&wake2DarkwakeDelay);
6530 						SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6531 						DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6532 						ts_sleepStart = 0;
6533 					}
6534 				}
6535 			}
6536 
6537 			// Reset state after exiting from dark wake.
6538 
6539 			if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6540 			    CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6541 				darkWakeMaintenance = false;
6542 				darkWakeToSleepASAP = false;
6543 				pciCantSleepValid   = false;
6544 				darkWakeSleepService = false;
6545 
6546 				if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6547 					// Remove the influence of display power assertion
6548 					// before next system wake.
6549 					if (wrangler) {
6550 						wrangler->changePowerStateForRootDomain(
6551 							kWranglerPowerStateMin );
6552 					}
6553 					removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6554 				}
6555 			}
6556 
6557 			// Entered dark mode.
6558 
6559 			if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6560 			    (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6561 				// Queue an evaluation of whether to remain in dark wake,
6562 				// and for how long. This serves the purpose of draining
6563 				// any assertions from the queue.
6564 
6565 				pmPowerStateQueue->submitPowerEvent(
6566 					kPowerEventPolicyStimulus,
6567 					(void *) kStimulusDarkWakeEntry,
6568 					_systemStateGeneration );
6569 			}
6570 		}
6571 
6572 #if DEVELOPMENT || DEBUG
6573 		if (currentPowerState != (uint32_t) oldPowerState) {
6574 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6575 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6576 			    "Finish Power State Trans.",
6577 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6578 			    getPowerStateString((uint32_t)oldPowerState),
6579 			    getPowerStateString(currentPowerState),
6580 			    _currentCapability,
6581 			    _pendingCapability,
6582 			    changeFlags,
6583 			    _systemStateGeneration,
6584 			    _systemMessageClientMask,
6585 			    request->getTag()
6586 			    );
6587 		}
6588 #endif /* DEVELOPMENT || DEBUG */
6589 
6590 		DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6591 		    getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6592 		    _currentCapability, _pendingCapability,
6593 		    changeFlags, _systemStateGeneration, _systemMessageClientMask,
6594 		    request->getTag());
6595 
6596 		if ((currentPowerState == ON_STATE) && pmAssertions) {
6597 			pmAssertions->reportCPUBitAccounting();
6598 		}
6599 
6600 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6601 			displayWakeCnt++;
6602 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6603 			if (clamshellExists && fullWakeThreadCall) {
6604 				AbsoluteTime deadline;
6605 				clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6606 				thread_call_enter_delayed(fullWakeThreadCall, deadline);
6607 			}
6608 #endif
6609 		} else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6610 			darkWakeCnt++;
6611 		}
6612 
6613 		// Update current system capability.
6614 		if (_currentCapability != _pendingCapability) {
6615 			_currentCapability = _pendingCapability;
6616 		}
6617 
6618 		// Update highest system capability.
6619 
6620 		_highestCapability |= _currentCapability;
6621 
6622 		if (darkWakePostTickle &&
6623 		    (kSystemTransitionWake == _systemTransitionType) &&
6624 		    (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6625 		    kDarkWakeFlagPromotionLate) {
6626 			darkWakePostTickle = false;
6627 			reportUserInput();
6628 		} else if (darkWakeExit) {
6629 			requestFullWake( kFullWakeReasonLocalUser );
6630 		}
6631 
6632 		// Reset tracepoint at completion of capability change,
6633 		// completion of wake transition, and aborted sleep transition.
6634 
6635 		if ((_systemTransitionType == kSystemTransitionCapability) ||
6636 		    (_systemTransitionType == kSystemTransitionWake) ||
6637 		    ((_systemTransitionType == kSystemTransitionSleep) &&
6638 		    (changeFlags & kIOPMNotDone))) {
6639 			setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6640 			tracePoint( kIOPMTracePointSystemUp );
6641 		}
6642 
6643 		_systemTransitionType = kSystemTransitionNone;
6644 		_systemMessageClientMask = 0;
6645 		toldPowerdCapWillChange  = false;
6646 
6647 		darkWakeLogClamp = false;
6648 
6649 		if (lowBatteryCondition) {
6650 			privateSleepSystem(kIOPMSleepReasonLowPower);
6651 		} else if (thermalEmergencyState) {
6652 			privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6653 		} else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6654 			// Request for full wake is removed while system is waking up to full wake
6655 			DLOG("DisplayOn fullwake request is removed\n");
6656 			handleSetDisplayPowerOn(false);
6657 		}
6658 
6659 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6660 			pmPowerStateQueue->submitPowerEvent(
6661 				kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6662 		}
6663 	}
6664 }
6665 
6666 //******************************************************************************
6667 // PM actions for graphics and audio.
6668 //******************************************************************************
6669 
6670 void
6671 IOPMrootDomain::overridePowerChangeForService(
6672 	IOService *             service,
6673 	IOPMActions *           actions,
6674 	const IOPMRequest *     request,
6675 	IOPMPowerStateIndex *   inOutPowerState,
6676 	IOPMPowerChangeFlags *  inOutChangeFlags )
6677 {
6678 	uint32_t powerState  = (uint32_t) *inOutPowerState;
6679 	uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6680 	const uint32_t actionFlags = actions->flags;
6681 
6682 	if (kSystemTransitionNone == _systemTransitionType) {
6683 		// Not in midst of a system transition.
6684 		// Do not set kPMActionsStatePowerClamped.
6685 	} else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6686 		bool enableClamp = false;
6687 
6688 		// For most drivers, enable the clamp during ON->Dark transition
6689 		// which has the kIOPMSynchronize flag set in changeFlags.
6690 		if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6691 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6692 		    (changeFlags & kIOPMSynchronize)) {
6693 			enableClamp = true;
6694 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6695 		    ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6696 		    ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6697 		    (changeFlags & kIOPMSynchronize)) {
6698 			enableClamp = true;
6699 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6700 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6701 		    (changeFlags & kIOPMSynchronize)) {
6702 			enableClamp = true;
6703 		} else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6704 		    (_systemTransitionType == kSystemTransitionSleep)) {
6705 			// For graphics drivers, clamp power when entering
6706 			// system sleep. Not when dropping to dark wake.
6707 			enableClamp = true;
6708 		}
6709 
6710 		if (enableClamp) {
6711 			actions->state |= kPMActionsStatePowerClamped;
6712 			DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6713 			    service->getName(), service->getRegistryEntryID(),
6714 			    _pendingCapability, powerState, changeFlags);
6715 		}
6716 	} else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6717 		bool disableClamp = false;
6718 
6719 		if ((actionFlags & (
6720 			    kPMActionsFlagIsDisplayWrangler |
6721 			    kPMActionsFlagIsGraphicsDriver)) &&
6722 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6723 			disableClamp = true;
6724 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6725 		    (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6726 			disableClamp = true;
6727 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6728 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6729 			disableClamp = true;
6730 		}
6731 
6732 		if (disableClamp) {
6733 			actions->state &= ~kPMActionsStatePowerClamped;
6734 			DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6735 			    service->getName(), service->getRegistryEntryID(),
6736 			    _pendingCapability, powerState, changeFlags);
6737 		}
6738 	}
6739 
6740 	if (actions->state & kPMActionsStatePowerClamped) {
6741 		uint32_t maxPowerState = 0;
6742 
6743 		// Determine the max power state allowed when clamp is enabled
6744 		if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6745 			// Parent intiated power state changes
6746 			if ((service->getPowerState() > maxPowerState) &&
6747 			    (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6748 				maxPowerState++;
6749 
6750 				// Remove lingering effects of any tickle before entering
6751 				// dark wake. It will take a new tickle to return to full
6752 				// wake, so the existing tickle state is useless.
6753 
6754 				if (changeFlags & kIOPMDomainDidChange) {
6755 					*inOutChangeFlags |= kIOPMExpireIdleTimer;
6756 				}
6757 			} else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6758 				maxPowerState++;
6759 			} else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6760 				maxPowerState = actions->darkWakePowerState;
6761 			}
6762 		} else {
6763 			// Deny all self-initiated changes when power is limited.
6764 			// Wrangler tickle should never defeat the limiter.
6765 			maxPowerState = service->getPowerState();
6766 		}
6767 
6768 		if (powerState > maxPowerState) {
6769 			DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6770 			    service->getName(), service->getRegistryEntryID(),
6771 			    powerState, maxPowerState, changeFlags);
6772 			*inOutPowerState = maxPowerState;
6773 
6774 			if (darkWakePostTickle &&
6775 			    (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6776 			    (changeFlags & kIOPMDomainWillChange) &&
6777 			    ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6778 			    kDarkWakeFlagPromotionEarly)) {
6779 				darkWakePostTickle = false;
6780 				reportUserInput();
6781 			}
6782 		}
6783 
6784 		if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
6785 			if (darkWakeLogClamp) {
6786 				AbsoluteTime    now;
6787 				uint64_t        nsec;
6788 
6789 				clock_get_uptime(&now);
6790 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
6791 				absolutetime_to_nanoseconds(now, &nsec);
6792 				DLOG("dark wake power clamped after %u ms\n",
6793 				    ((int)((nsec) / NSEC_PER_MSEC)));
6794 			}
6795 			darkWakePowerClamped = true;
6796 		}
6797 	}
6798 }
6799 
6800 void
6801 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
6802 	IOService *     service,
6803 	IOPMActions *   actions )
6804 {
6805 #if DISPLAY_WRANGLER_PRESENT
6806 	// Warning: Not running in PM work loop context - don't modify state !!!
6807 	// Trap tickle directed to IODisplayWrangler while running with graphics
6808 	// capability suppressed.
6809 
6810 	assert(service == wrangler);
6811 
6812 	clock_get_uptime(&userActivityTime);
6813 	bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
6814 	    || (lastSleepReason == kIOPMSleepReasonMaintenance)
6815 	    || (lastSleepReason == kIOPMSleepReasonSoftware));
6816 	if (aborting) {
6817 		userActivityCount++;
6818 		DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
6819 		    userActivityCount, lastSleepReason);
6820 	}
6821 
6822 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
6823 		DLOG("display wrangler tickled\n");
6824 		if (kIOLogPMRootDomain & gIOKitDebug) {
6825 			OSReportWithBacktrace("Dark wake display tickle");
6826 		}
6827 		if (pmPowerStateQueue) {
6828 			pmPowerStateQueue->submitPowerEvent(
6829 				kPowerEventPolicyStimulus,
6830 				(void *) kStimulusDarkWakeActivityTickle,
6831 				true /* set wake type */ );
6832 		}
6833 	}
6834 #endif /* DISPLAY_WRANGLER_PRESENT */
6835 }
6836 
6837 void
6838 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
6839 	IOService *             service,
6840 	IOPMActions *           actions,
6841 	const OSSymbol *        powerClient,
6842 	IOPMPowerStateIndex     oldPowerState,
6843 	IOPMPowerStateIndex     newPowerState )
6844 {
6845 #if DISPLAY_WRANGLER_PRESENT
6846 	assert(service == wrangler);
6847 
6848 	// This function implements half of the user active detection
6849 	// by monitoring changes to the display wrangler's device desire.
6850 	//
6851 	// User becomes active when either:
6852 	// 1. Wrangler's DeviceDesire increases to max, but wrangler is already
6853 	//    in max power state. This desire change in absence of a power state
6854 	//    change is detected within. This handles the case when user becomes
6855 	//    active while the display is already lit by setDisplayPowerOn().
6856 	//
6857 	// 2. Power state change to max, and DeviceDesire is also at max.
6858 	//    Handled by displayWranglerNotification().
6859 	//
6860 	// User becomes inactive when DeviceDesire drops to sleep state or below.
6861 
6862 	DLOG("wrangler %s (ps %u, %u->%u)\n",
6863 	    powerClient->getCStringNoCopy(),
6864 	    (uint32_t) service->getPowerState(),
6865 	    (uint32_t) oldPowerState, (uint32_t) newPowerState);
6866 
6867 	if (powerClient == gIOPMPowerClientDevice) {
6868 		if ((newPowerState > oldPowerState) &&
6869 		    (newPowerState == kWranglerPowerStateMax) &&
6870 		    (service->getPowerState() == kWranglerPowerStateMax)) {
6871 			evaluatePolicy( kStimulusEnterUserActiveState );
6872 		} else if ((newPowerState < oldPowerState) &&
6873 		    (newPowerState <= kWranglerPowerStateSleep)) {
6874 			evaluatePolicy( kStimulusLeaveUserActiveState );
6875 		}
6876 	}
6877 
6878 	if (newPowerState <= kWranglerPowerStateSleep) {
6879 		evaluatePolicy( kStimulusDisplayWranglerSleep );
6880 	} else if (newPowerState == kWranglerPowerStateMax) {
6881 		evaluatePolicy( kStimulusDisplayWranglerWake );
6882 	}
6883 #endif /* DISPLAY_WRANGLER_PRESENT */
6884 }
6885 
6886 //******************************************************************************
6887 // User active state management
6888 //******************************************************************************
6889 
6890 void
6891 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
6892 {
6893 #if DISPLAY_WRANGLER_PRESENT
6894 	_preventUserActive = prevent;
6895 	if (wrangler && !_preventUserActive) {
6896 		// Allowing transition to user active, but the wrangler may have
6897 		// already powered ON in case of sleep cancel/revert. Poll the
6898 		// same conditions checked for in displayWranglerNotification()
6899 		// to bring the user active state up to date.
6900 
6901 		if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
6902 		    (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
6903 		    kWranglerPowerStateMax)) {
6904 			evaluatePolicy( kStimulusEnterUserActiveState );
6905 		}
6906 	}
6907 #endif /* DISPLAY_WRANGLER_PRESENT */
6908 }
6909 
6910 //******************************************************************************
6911 // Approve usage of delayed child notification by PM.
6912 //******************************************************************************
6913 
6914 bool
6915 IOPMrootDomain::shouldDelayChildNotification(
6916 	IOService * service )
6917 {
6918 	if ((kFullWakeReasonNone == fullWakeReason) &&
6919 	    (kSystemTransitionWake == _systemTransitionType)) {
6920 		DLOG("%s: delay child notify\n", service->getName());
6921 		return true;
6922 	}
6923 	return false;
6924 }
6925 
6926 //******************************************************************************
6927 // PM actions for PCI device.
6928 //******************************************************************************
6929 
6930 void
6931 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
6932 	IOService *             service,
6933 	IOPMActions *           actions,
6934 	const IOPMRequest *     request,
6935 	IOPMPowerStateIndex     powerState,
6936 	IOPMPowerChangeFlags *  inOutChangeFlags )
6937 {
6938 	pmTracer->tracePCIPowerChange(
6939 		PMTraceWorker::kPowerChangeStart,
6940 		service, *inOutChangeFlags,
6941 		(actions->flags & kPMActionsPCIBitNumberMask));
6942 }
6943 
6944 void
6945 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
6946 	IOService *             service,
6947 	IOPMActions *           actions,
6948 	const IOPMRequest *     request,
6949 	IOPMPowerStateIndex     powerState,
6950 	IOPMPowerChangeFlags    changeFlags )
6951 {
6952 	pmTracer->tracePCIPowerChange(
6953 		PMTraceWorker::kPowerChangeCompleted,
6954 		service, changeFlags,
6955 		(actions->flags & kPMActionsPCIBitNumberMask));
6956 }
6957 
6958 //******************************************************************************
6959 // registerInterest
6960 //
6961 // Override IOService::registerInterest() for root domain clients.
6962 //******************************************************************************
6963 
6964 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
6965 {
6966 	friend class IOPMrootDomain;
6967 	OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
6968 
6969 protected:
6970 	uint32_t        ackTimeoutCnt;
6971 	uint32_t        msgType;    // Last type seen by the message filter
6972 	uint32_t        lastSleepWakeMsgType;
6973 	uint32_t        msgIndex;
6974 	uint32_t        maxMsgDelayMS;
6975 	uint32_t        maxAckDelayMS;
6976 	uint64_t        msgAbsTime;
6977 	uint64_t        uuid0;
6978 	uint64_t        uuid1;
6979 	OSSharedPtr<const OSSymbol> identifier;
6980 	OSSharedPtr<const OSSymbol> clientName;
6981 };
6982 
6983 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
6984 
6985 OSSharedPtr<IONotifier>
6986 IOPMrootDomain::registerInterest(
6987 	const OSSymbol * typeOfInterest,
6988 	IOServiceInterestHandler handler,
6989 	void * target, void * ref )
6990 {
6991 	IOPMServiceInterestNotifier* notifier;
6992 	bool            isSystemCapabilityClient;
6993 	bool            isKernelCapabilityClient;
6994 	IOReturn        rc = kIOReturnError;
6995 
6996 	isSystemCapabilityClient = typeOfInterest &&
6997 	    typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
6998 
6999 	isKernelCapabilityClient = typeOfInterest &&
7000 	    typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7001 
7002 	if (isSystemCapabilityClient) {
7003 		typeOfInterest = gIOAppPowerStateInterest;
7004 	}
7005 
7006 	notifier = new IOPMServiceInterestNotifier;
7007 	if (!notifier) {
7008 		return NULL;
7009 	}
7010 
7011 	if (notifier->init()) {
7012 		rc  = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7013 	}
7014 	if (rc != kIOReturnSuccess) {
7015 		OSSafeReleaseNULL(notifier);
7016 		return NULL;
7017 	}
7018 
7019 	notifier->ackTimeoutCnt = 0;
7020 
7021 	if (pmPowerStateQueue) {
7022 		if (isSystemCapabilityClient) {
7023 			notifier->retain();
7024 			if (pmPowerStateQueue->submitPowerEvent(
7025 				    kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7026 				notifier->release();
7027 			}
7028 		}
7029 
7030 		if (isKernelCapabilityClient) {
7031 			notifier->retain();
7032 			if (pmPowerStateQueue->submitPowerEvent(
7033 				    kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7034 				notifier->release();
7035 			}
7036 		}
7037 	}
7038 
7039 	OSSharedPtr<OSData> data;
7040 	uint8_t *uuid = NULL;
7041 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7042 	if (kext) {
7043 		data = kext->copyUUID();
7044 	}
7045 	if (data && (data->getLength() == sizeof(uuid_t))) {
7046 		uuid = (uint8_t *)(data->getBytesNoCopy());
7047 
7048 		notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7049 		    ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7050 		    ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7051 		notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7052 		    ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7053 		    ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7054 
7055 		notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7056 	}
7057 	return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7058 }
7059 
7060 //******************************************************************************
7061 // systemMessageFilter
7062 //
7063 //******************************************************************************
7064 
7065 bool
7066 IOPMrootDomain::systemMessageFilter(
7067 	void * object, void * arg1, void * arg2, void * arg3 )
7068 {
7069 	const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7070 	bool  isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7071 	bool  isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7072 	bool  isCapClient = false;
7073 	bool  allow = false;
7074 	OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7075 	IOPMServiceInterestNotifier *notifier;
7076 
7077 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7078 
7079 	do {
7080 		// When powerd and kernel priority clients register capability interest,
7081 		// the power tree is sync'ed to inform those clients about the current
7082 		// system capability. Only allow capability change messages during sync.
7083 		if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7084 		    (!isCapMsg || !_joinedCapabilityClients ||
7085 		    !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7086 			break;
7087 		}
7088 
7089 		// Capability change message for powerd and kernel clients
7090 		if (isCapMsg) {
7091 			// Kernel priority clients
7092 			if ((context->notifyType == kNotifyPriority) ||
7093 			    (context->notifyType == kNotifyCapabilityChangePriority)) {
7094 				isCapClient = true;
7095 			}
7096 
7097 			// powerd will maintain two client registrations with root domain.
7098 			// isCapPowerd will be TRUE for any message targeting the powerd
7099 			// exclusive (capability change) interest registration.
7100 			if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7101 				isCapClient = true;
7102 			}
7103 		}
7104 
7105 		if (isCapClient) {
7106 			IOPMSystemCapabilityChangeParameters * capArgs =
7107 			    (IOPMSystemCapabilityChangeParameters *) arg2;
7108 
7109 			if (kSystemTransitionNewCapClient == _systemTransitionType) {
7110 				capArgs->fromCapabilities = 0;
7111 				capArgs->toCapabilities = _currentCapability;
7112 				capArgs->changeFlags = 0;
7113 			} else {
7114 				capArgs->fromCapabilities = _currentCapability;
7115 				capArgs->toCapabilities = _pendingCapability;
7116 
7117 				if (context->isPreChange) {
7118 					capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7119 				} else {
7120 					capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7121 				}
7122 
7123 				if (isCapPowerd && context->isPreChange) {
7124 					toldPowerdCapWillChange = true;
7125 				}
7126 			}
7127 
7128 			// App level capability change messages must only go to powerd.
7129 			// Wait for response post-change if capabilitiy is increasing.
7130 			// Wait for response pre-change if capability is decreasing.
7131 
7132 			if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7133 			    ((capabilityLoss && context->isPreChange) ||
7134 			    (!capabilityLoss && !context->isPreChange))) {
7135 				*waitForReply = kOSBooleanTrue;
7136 			}
7137 
7138 			allow = true;
7139 			break;
7140 		}
7141 
7142 		// powerd will always receive CanSystemSleep, even for a demand sleep.
7143 		// It will also have a final chance to veto sleep after all clients
7144 		// have responded to SystemWillSleep
7145 
7146 		if ((kIOMessageCanSystemSleep == context->messageType) ||
7147 		    (kIOMessageSystemWillNotSleep == context->messageType)) {
7148 			if (isCapPowerd) {
7149 				allow = true;
7150 				break;
7151 			}
7152 
7153 			// Demand sleep, don't ask apps for permission
7154 			if (context->changeFlags & kIOPMSkipAskPowerDown) {
7155 				break;
7156 			}
7157 		}
7158 
7159 		if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7160 			if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7161 			    (fullToDarkReason == kIOPMSleepReasonIdle)) {
7162 				allow = true;
7163 			}
7164 			break;
7165 		}
7166 
7167 		// Drop capability change messages for legacy clients.
7168 		// Drop legacy system sleep messages for powerd capability interest.
7169 		if (isCapMsg || isCapPowerd) {
7170 			break;
7171 		}
7172 
7173 		// Not a capability change message.
7174 		// Perform message filtering based on _systemMessageClientMask.
7175 
7176 		if ((context->notifyType == kNotifyApps) &&
7177 		    (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7178 			if (!notifier) {
7179 				break;
7180 			}
7181 
7182 			if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7183 			    (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7184 				break; // drop any duplicate WillPowerOn for AOT devices
7185 			}
7186 
7187 			allow = true;
7188 
7189 			if (waitForReply) {
7190 				if (notifier->ackTimeoutCnt >= 3) {
7191 					*waitForReply = kOSBooleanFalse;
7192 				} else {
7193 					*waitForReply = kOSBooleanTrue;
7194 				}
7195 			}
7196 		} else if ((context->notifyType == kNotifyPriority) &&
7197 		    (_systemMessageClientMask & kSystemMessageClientKernel)) {
7198 			allow = true;
7199 		}
7200 
7201 		// Check sleep/wake message ordering
7202 		if (allow) {
7203 			if (context->messageType == kIOMessageSystemWillSleep ||
7204 			    context->messageType == kIOMessageSystemWillPowerOn ||
7205 			    context->messageType == kIOMessageSystemHasPoweredOn) {
7206 				notifier->lastSleepWakeMsgType = context->messageType;
7207 			}
7208 		}
7209 	} while (false);
7210 
7211 	if (allow && isCapMsg && _joinedCapabilityClients) {
7212 		_joinedCapabilityClients->removeObject((OSObject *) object);
7213 		if (_joinedCapabilityClients->getCount() == 0) {
7214 			DMSG("destroyed capability client set %p\n",
7215 			    OBFUSCATE(_joinedCapabilityClients.get()));
7216 			_joinedCapabilityClients.reset();
7217 		}
7218 	}
7219 	if (notifier) {
7220 		// Record the last seen message type even if the message is dropped
7221 		// for traceFilteredNotification().
7222 		notifier->msgType = context->messageType;
7223 	}
7224 
7225 	return allow;
7226 }
7227 
7228 //******************************************************************************
7229 // setMaintenanceWakeCalendar
7230 //
7231 //******************************************************************************
7232 
7233 IOReturn
7234 IOPMrootDomain::setMaintenanceWakeCalendar(
7235 	const IOPMCalendarStruct * calendar )
7236 {
7237 	OSSharedPtr<OSData> data;
7238 	IOReturn ret = 0;
7239 
7240 	if (!calendar) {
7241 		return kIOReturnBadArgument;
7242 	}
7243 
7244 	data = OSData::withValue(*calendar);
7245 	if (!data) {
7246 		return kIOReturnNoMemory;
7247 	}
7248 
7249 	if (kPMCalendarTypeMaintenance == calendar->selector) {
7250 		ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7251 	} else if (kPMCalendarTypeSleepService == calendar->selector) {
7252 		ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7253 	}
7254 
7255 	return ret;
7256 }
7257 
7258 // MARK: -
7259 // MARK: Display Wrangler
7260 
7261 //******************************************************************************
7262 // displayWranglerNotification
7263 //
7264 // Handle the notification when the IODisplayWrangler changes power state.
7265 //******************************************************************************
7266 
7267 IOReturn
7268 IOPMrootDomain::displayWranglerNotification(
7269 	void * target, void * refCon,
7270 	UInt32 messageType, IOService * service,
7271 	void * messageArgument, vm_size_t argSize )
7272 {
7273 #if DISPLAY_WRANGLER_PRESENT
7274 	IOPMPowerStateIndex                 displayPowerState;
7275 	IOPowerStateChangeNotification *    params =
7276 	    (IOPowerStateChangeNotification *) messageArgument;
7277 
7278 	if ((messageType != kIOMessageDeviceWillPowerOff) &&
7279 	    (messageType != kIOMessageDeviceHasPoweredOn)) {
7280 		return kIOReturnUnsupported;
7281 	}
7282 
7283 	ASSERT_GATED();
7284 	if (!gRootDomain) {
7285 		return kIOReturnUnsupported;
7286 	}
7287 
7288 	displayPowerState = params->stateNumber;
7289 	DLOG("wrangler %s ps %d\n",
7290 	    getIOMessageString(messageType), (uint32_t) displayPowerState);
7291 
7292 	switch (messageType) {
7293 	case kIOMessageDeviceWillPowerOff:
7294 		// Display wrangler has dropped power due to display idle
7295 		// or force system sleep.
7296 		//
7297 		// 4 Display ON             kWranglerPowerStateMax
7298 		// 3 Display Dim            kWranglerPowerStateDim
7299 		// 2 Display Sleep          kWranglerPowerStateSleep
7300 		// 1 Not visible to user
7301 		// 0 Not visible to user    kWranglerPowerStateMin
7302 
7303 		if (displayPowerState <= kWranglerPowerStateSleep) {
7304 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7305 		}
7306 		break;
7307 
7308 	case kIOMessageDeviceHasPoweredOn:
7309 		// Display wrangler has powered on due to user activity
7310 		// or wake from sleep.
7311 
7312 		if (kWranglerPowerStateMax == displayPowerState) {
7313 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7314 
7315 			// See comment in handleUpdatePowerClientForDisplayWrangler
7316 			if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7317 			    kWranglerPowerStateMax) {
7318 				gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7319 			}
7320 		}
7321 		break;
7322 	}
7323 #endif /* DISPLAY_WRANGLER_PRESENT */
7324 	return kIOReturnUnsupported;
7325 }
7326 
7327 //******************************************************************************
7328 // reportUserInput
7329 //
7330 //******************************************************************************
7331 
7332 void
7333 IOPMrootDomain::updateUserActivity( void )
7334 {
7335 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7336 	clock_get_uptime(&userActivityTime);
7337 	bool aborting =  ((lastSleepReason == kIOPMSleepReasonSoftware)
7338 	    || (lastSleepReason == kIOPMSleepReasonIdle)
7339 	    || (lastSleepReason == kIOPMSleepReasonMaintenance));
7340 	if (aborting) {
7341 		userActivityCount++;
7342 		DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7343 	}
7344 #endif
7345 }
7346 void
7347 IOPMrootDomain::reportUserInput( void )
7348 {
7349 	if (wrangler) {
7350 		wrangler->activityTickle(0, 0);
7351 	}
7352 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7353 	// Update user activity
7354 	updateUserActivity();
7355 
7356 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7357 		// update user active abs time
7358 		clock_get_uptime(&gUserActiveAbsTime);
7359 		pmPowerStateQueue->submitPowerEvent(
7360 			kPowerEventPolicyStimulus,
7361 			(void *) kStimulusDarkWakeActivityTickle,
7362 			true /* set wake type */ );
7363 	}
7364 #endif
7365 }
7366 
7367 void
7368 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7369 {
7370 #if DISPLAY_WRANGLER_PRESENT
7371 	if (wrangler) {
7372 		wrangler->activityTickle(0, 0);
7373 	}
7374 #else
7375 	if (!device) {
7376 		DLOG("requestUserActive: device is null\n");
7377 		return;
7378 	}
7379 	OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7380 	uint64_t registryID = device->getRegistryEntryID();
7381 
7382 	if (!deviceName || !registryID) {
7383 		DLOG("requestUserActive: no device name or registry entry\n");
7384 		return;
7385 	}
7386 	const char *name = deviceName->getCStringNoCopy();
7387 	char payload[128];
7388 	snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7389 	DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7390 	messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7391 #endif
7392 }
7393 
7394 //******************************************************************************
7395 // latchDisplayWranglerTickle
7396 //******************************************************************************
7397 
7398 bool
7399 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7400 {
7401 #if DISPLAY_WRANGLER_PRESENT
7402 	if (latch) {
7403 		if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7404 		    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7405 		    !checkSystemCanSustainFullWake()) {
7406 			// Currently in dark wake, and not transitioning to full wake.
7407 			// Full wake is unsustainable, so latch the tickle to prevent
7408 			// the display from lighting up momentarily.
7409 			wranglerTickled = true;
7410 		} else {
7411 			wranglerTickled = false;
7412 		}
7413 	} else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7414 		wranglerTickled = false;
7415 
7416 		pmPowerStateQueue->submitPowerEvent(
7417 			kPowerEventPolicyStimulus,
7418 			(void *) kStimulusDarkWakeActivityTickle );
7419 	}
7420 
7421 	return wranglerTickled;
7422 #else  /* ! DISPLAY_WRANGLER_PRESENT */
7423 	return false;
7424 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7425 }
7426 
7427 //******************************************************************************
7428 // setDisplayPowerOn
7429 //
7430 // For root domain user client
7431 //******************************************************************************
7432 
7433 void
7434 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7435 {
7436 	pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7437 	    (void *) NULL, options );
7438 }
7439 
7440 // MARK: -
7441 // MARK: System PM Policy
7442 
7443 //******************************************************************************
7444 // checkSystemSleepAllowed
7445 //
7446 //******************************************************************************
7447 
7448 bool
7449 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7450     uint32_t     sleepReason )
7451 {
7452 	uint32_t err = 0;
7453 
7454 	// Conditions that prevent idle and demand system sleep.
7455 
7456 	do {
7457 		if (gSleepDisabledFlag) {
7458 			err = kPMConfigPreventSystemSleep;
7459 			break;
7460 		}
7461 
7462 		if (userDisabledAllSleep) {
7463 			err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7464 			break;
7465 		}
7466 
7467 		if (systemBooting || systemShutdown || gWillShutdown) {
7468 			err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7469 			break;
7470 		}
7471 
7472 		if (options == 0) {
7473 			break;
7474 		}
7475 
7476 		// Conditions above pegs the system at full wake.
7477 		// Conditions below prevent system sleep but does not prevent
7478 		// dark wake, and must be called from gated context.
7479 
7480 #if !CONFIG_SLEEP
7481 		err = kPMConfigPreventSystemSleep;    // 3. config does not support sleep
7482 		break;
7483 #endif
7484 
7485 		if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7486 			break; // always sleep on low battery or when in thermal warning/emergency state
7487 		}
7488 
7489 		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7490 			break; // always sleep on dark wake thermal emergencies
7491 		}
7492 
7493 		if (preventSystemSleepList->getCount() != 0) {
7494 			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7495 			break;
7496 		}
7497 
7498 		if (_driverKitMatchingAssertionCount != 0) {
7499 			err = kPMCPUAssertion;
7500 			break;
7501 		}
7502 
7503 		// Check for any dexts currently being added to the PM tree. Sleeping while
7504 		// this is in flight can cause IOServicePH to timeout.
7505 		if (!IOServicePH::checkPMReady()) {
7506 #if !defined(XNU_TARGET_OS_OSX)
7507 			// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7508 			// in dark wake for long periods of time, which causes issues as apps were
7509 			// already informed of sleep during the f->9 transition. As a temporary
7510 			// measure, always full wake if we hit this specific condition.
7511 			pmPowerStateQueue->submitPowerEvent(
7512 				kPowerEventPolicyStimulus,
7513 				(void *) kStimulusDarkWakeActivityTickle);
7514 #endif
7515 			err = kPMDKNotReady;
7516 			break;
7517 		}
7518 
7519 		if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7520 		    kIOPMDriverAssertionLevelOn) {
7521 			err = kPMCPUAssertion; // 5. CPU assertion
7522 			break;
7523 		}
7524 
7525 		if (pciCantSleepValid) {
7526 			if (pciCantSleepFlag) {
7527 				err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7528 			}
7529 			break;
7530 		} else if (sleepSupportedPEFunction &&
7531 		    CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7532 			IOReturn ret;
7533 			OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7534 			ret = getPlatform()->callPlatformFunction(
7535 				sleepSupportedPEFunction.get(), false,
7536 				NULL, NULL, NULL, NULL);
7537 			pciCantSleepValid = true;
7538 			pciCantSleepFlag  = false;
7539 			if ((platformSleepSupport & kPCICantSleep) ||
7540 			    ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7541 				err = 6; // 6. PCI card does not support PM
7542 				pciCantSleepFlag = true;
7543 				break;
7544 			}
7545 		}
7546 	}while (false);
7547 
7548 	if (err) {
7549 		DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7550 		return false;
7551 	}
7552 	return true;
7553 }
7554 
7555 bool
7556 IOPMrootDomain::checkSystemSleepEnabled( void )
7557 {
7558 	return checkSystemSleepAllowed(0, 0);
7559 }
7560 
7561 bool
7562 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7563 {
7564 	ASSERT_GATED();
7565 	return checkSystemSleepAllowed(1, sleepReason);
7566 }
7567 
7568 //******************************************************************************
7569 // checkSystemCanSustainFullWake
7570 //******************************************************************************
7571 
7572 bool
7573 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7574 {
7575 	if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7576 		// Low battery wake, or received a low battery notification
7577 		// while system is awake. This condition will persist until
7578 		// the following wake.
7579 		return false;
7580 	}
7581 
7582 	if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7583 		// Graphics state is unknown and external display might not be probed.
7584 		// Do not incorporate state that requires graphics to be in max power
7585 		// such as desktopMode or clamshellDisabled.
7586 
7587 		if (!acAdaptorConnected) {
7588 			DLOG("full wake check: no AC\n");
7589 			return false;
7590 		}
7591 	}
7592 	return true;
7593 }
7594 
7595 //******************************************************************************
7596 // mustHibernate
7597 //******************************************************************************
7598 
7599 #if HIBERNATION
7600 
7601 bool
7602 IOPMrootDomain::mustHibernate( void )
7603 {
7604 	return lowBatteryCondition || thermalWarningState;
7605 }
7606 
7607 #endif /* HIBERNATION */
7608 
7609 //******************************************************************************
7610 // AOT
7611 //******************************************************************************
7612 
7613 // Tables for accumulated days in year by month, latter used for leap years
7614 
7615 static const unsigned int daysbymonth[] =
7616 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7617 
7618 static const unsigned int lydaysbymonth[] =
7619 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7620 
7621 static int __unused
7622 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7623 {
7624 	const unsigned int *    dbm = daysbymonth;
7625 	clock_sec_t             n, x, y, z;
7626 
7627 	// Calculate seconds, minutes and hours
7628 
7629 	n = secs % (24 * 3600);
7630 	dt->second = n % 60;
7631 	n /= 60;
7632 	dt->minute = n % 60;
7633 	dt->hour = (typeof(dt->hour))(n / 60);
7634 
7635 	// Calculate day of week
7636 
7637 	n = secs / (24 * 3600);
7638 //	dt->dayWeek = (n + 4) % 7;
7639 
7640 	// Calculate year
7641 	// Rebase from days since Unix epoch (1/1/1970) store in 'n',
7642 	// to days since 1/1/1968 to start on 4 year cycle, beginning
7643 	// on a leap year.
7644 
7645 	n += (366 + 365);
7646 
7647 	// Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7648 	// Valid before 2100, since 2100 is not a leap year.
7649 
7650 	x = n / 1461;       // number of 4 year cycles
7651 	y = n % 1461;       // days into current 4 year cycle
7652 	z = 1968 + (4 * x);
7653 
7654 	// Add in years in the current 4 year cycle
7655 
7656 	if (y >= 366) {
7657 		y -= 366;   // days after the leap year
7658 		n = y % 365; // days into the current year
7659 		z += (1 + y / 365); // years after the past 4-yr cycle
7660 	} else {
7661 		n = y;
7662 		dbm = lydaysbymonth;
7663 	}
7664 	if (z > 2099) {
7665 		return 0;
7666 	}
7667 
7668 	dt->year = (typeof(dt->year))z;
7669 
7670 	// Adjust remaining days value to start at 1
7671 
7672 	n += 1;
7673 
7674 	// Calculate month
7675 
7676 	for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7677 		continue;
7678 	}
7679 	dt->month = (typeof(dt->month))x;
7680 
7681 	// Calculate day of month
7682 
7683 	dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7684 
7685 	return 1;
7686 }
7687 
7688 static clock_sec_t
7689 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7690 {
7691 	const unsigned int *    dbm = daysbymonth;
7692 	long                    y, secs, days;
7693 
7694 	if (dt->year < 1970 || dt->month > 12) {
7695 		return 0;
7696 	}
7697 
7698 	// Seconds elapsed in the current day
7699 
7700 	secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7701 
7702 	// Number of days from 1/1/70 to beginning of current year
7703 	// Account for extra day every 4 years starting at 1973
7704 
7705 	y = dt->year - 1970;
7706 	days = (y * 365) + ((y + 1) / 4);
7707 
7708 	// Change table if current year is a leap year
7709 
7710 	if ((dt->year % 4) == 0) {
7711 		dbm = lydaysbymonth;
7712 	}
7713 
7714 	// Add in days elapsed in the current year
7715 
7716 	days += (dt->day - 1) + dbm[dt->month - 1];
7717 
7718 	// Add accumulated days to accumulated seconds
7719 
7720 	secs += 24 * 3600 * days;
7721 
7722 	return secs;
7723 }
7724 
7725 unsigned long
7726 IOPMrootDomain::getRUN_STATE(void)
7727 {
7728 	return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
7729 }
7730 
7731 bool
7732 IOPMrootDomain::isAOTMode()
7733 {
7734 	return _aotNow;
7735 }
7736 
7737 IOReturn
7738 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
7739 {
7740 	clock_sec_t     nowsecs, wakesecs;
7741 	clock_usec_t    nowmicrosecs, wakemicrosecs;
7742 	uint64_t        nowAbs, wakeAbs;
7743 
7744 	if (!_aotMode) {
7745 		return kIOReturnNotReady;
7746 	}
7747 
7748 	clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
7749 	wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
7750 	if (wakeAbs < nowAbs) {
7751 		printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
7752 		wakeAbs = nowAbs;
7753 	}
7754 	wakeAbs -= nowAbs;
7755 	absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
7756 
7757 	wakesecs += nowsecs;
7758 	wakemicrosecs += nowmicrosecs;
7759 	if (wakemicrosecs >= USEC_PER_SEC) {
7760 		wakesecs++;
7761 		wakemicrosecs -= USEC_PER_SEC;
7762 	}
7763 	if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
7764 		wakesecs++;
7765 	}
7766 
7767 	IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
7768 
7769 	if (_aotWakeTimeContinuous != wakeContinuousTime) {
7770 		_aotWakeTimeContinuous = wakeContinuousTime;
7771 		IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
7772 	}
7773 	_aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
7774 	_aotWakeTimeUTC               = wakesecs;
7775 
7776 	return kIOReturnSuccess;
7777 }
7778 
7779 // assumes WAKEEVENT_LOCK
7780 bool
7781 IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
7782 {
7783 	bool exitNow = false;
7784 	const char * reason = "";
7785 
7786 	if (!_aotNow) {
7787 		return false;
7788 	}
7789 
7790 	if (software) {
7791 		exitNow = true;
7792 		_aotMetrics->softwareRequestCount++;
7793 		reason = "software request";
7794 	} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
7795 		exitNow = true;
7796 		reason = gWakeReasonString;
7797 	} else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
7798 		exitNow = true;
7799 		_aotMetrics->noTimeSetCount++;
7800 		reason = "flipbook expired";
7801 	} else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
7802 		clock_sec_t     sec;
7803 		clock_usec_t    usec;
7804 		clock_get_calendar_microtime(&sec, &usec);
7805 		if (_calendarWakeAlarmUTC <= sec) {
7806 			exitNow = true;
7807 			_aotMetrics->rtcAlarmsCount++;
7808 			reason = "user alarm";
7809 		}
7810 	}
7811 	if (exitNow) {
7812 		_aotPendingFlags |= kIOPMWakeEventAOTExit;
7813 		IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
7814 		    reason,
7815 		    _aotMetrics->sleepCount,
7816 		    _aotMetrics->possibleCount,
7817 		    _aotMetrics->confirmedPossibleCount,
7818 		    _aotMetrics->rejectedPossibleCount,
7819 		    _aotMetrics->expiredPossibleCount,
7820 		    _aotMetrics->noTimeSetCount,
7821 		    _aotMetrics->rtcAlarmsCount);
7822 	}
7823 	return exitNow;
7824 }
7825 
7826 void
7827 IOPMrootDomain::aotExit(bool cps)
7828 {
7829 	uint32_t savedMessageMask;
7830 
7831 	ASSERT_GATED();
7832 	_aotNow = false;
7833 	_aotReadyToFullWake = false;
7834 	if (_aotTimerScheduled) {
7835 		_aotTimerES->cancelTimeout();
7836 		_aotTimerScheduled = false;
7837 	}
7838 	updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
7839 
7840 	_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
7841 	_aotLastWakeTime = 0;
7842 	if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
7843 		WAKEEVENT_LOCK();
7844 		strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
7845 		    gWakeReasonString,
7846 		    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
7847 		WAKEEVENT_UNLOCK();
7848 	}
7849 
7850 	_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
7851 
7852 	// Preserve the message mask since a system wake transition
7853 	// may have already started and initialized the mask.
7854 	savedMessageMask = _systemMessageClientMask;
7855 	_systemMessageClientMask = kSystemMessageClientLegacyApp;
7856 	tellClients(kIOMessageSystemWillPowerOn);
7857 	_systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
7858 
7859 	if (cps) {
7860 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
7861 	}
7862 }
7863 
7864 void
7865 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
7866 {
7867 	bool exitNow;
7868 
7869 	IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
7870 
7871 	WAKEEVENT_LOCK();
7872 	exitNow = aotShouldExit(false, false);
7873 	if (timer != NULL) {
7874 		_aotTimerScheduled = false;
7875 	}
7876 	WAKEEVENT_UNLOCK();
7877 	if (exitNow) {
7878 		aotExit(true);
7879 	} else {
7880 #if 0
7881 		if (_aotLingerTime) {
7882 			uint64_t deadline;
7883 			IOLog("aot linger before sleep\n");
7884 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
7885 			clock_delay_until(deadline);
7886 		}
7887 #endif
7888 		privateSleepSystem(kIOPMSleepReasonSoftware);
7889 	}
7890 }
7891 
7892 //******************************************************************************
7893 // adjustPowerState
7894 //
7895 // Conditions that affect our wake/sleep decision has changed.
7896 // If conditions dictate that the system must remain awake, clamp power
7897 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
7898 // is TRUE, then remove the power clamp and allow the power state to drop
7899 // to SLEEP_STATE.
7900 //******************************************************************************
7901 
7902 void
7903 IOPMrootDomain::adjustPowerState( bool sleepASAP )
7904 {
7905 	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d\n",
7906 	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled);
7907 
7908 	ASSERT_GATED();
7909 
7910 	if (_aotNow) {
7911 		bool exitNow;
7912 
7913 		if (AOT_STATE != getPowerState()) {
7914 			return;
7915 		}
7916 		WAKEEVENT_LOCK();
7917 		exitNow = aotShouldExit(true, false);
7918 		if (!exitNow
7919 		    && !_aotTimerScheduled
7920 		    && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
7921 			_aotTimerScheduled = true;
7922 			if (_aotLingerTime) {
7923 				_aotTimerES->setTimeout(_aotLingerTime);
7924 			} else {
7925 				_aotTimerES->setTimeout(800, kMillisecondScale);
7926 			}
7927 		}
7928 		WAKEEVENT_UNLOCK();
7929 		if (exitNow) {
7930 			aotExit(true);
7931 		} else {
7932 			_aotReadyToFullWake = true;
7933 			if (!_aotTimerScheduled) {
7934 				if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
7935 					// Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
7936 					// Doing so will result in the sleep being cancelled anyway,
7937 					// but this check avoids unnecessary thrashing in the power state engine.
7938 					return;
7939 				}
7940 				privateSleepSystem(kIOPMSleepReasonSoftware);
7941 			}
7942 		}
7943 		return;
7944 	}
7945 
7946 	if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
7947 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
7948 	} else if (sleepASAP) {
7949 		changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
7950 	}
7951 }
7952 
7953 void
7954 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
7955 {
7956 	if (powerOn) {
7957 		if (!checkSystemCanSustainFullWake()) {
7958 			DLOG("System cannot sustain full wake\n");
7959 			return;
7960 		}
7961 
7962 		// Force wrangler to max power state. If system is in dark wake
7963 		// this alone won't raise the wrangler's power state.
7964 		if (wrangler) {
7965 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
7966 		}
7967 
7968 		// System in dark wake, always requesting full wake should
7969 		// not have any bad side-effects, even if the request fails.
7970 
7971 		if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
7972 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
7973 			requestFullWake( kFullWakeReasonDisplayOn );
7974 		}
7975 	} else {
7976 		// Relenquish desire to power up display.
7977 		// Must first transition to state 1 since wrangler doesn't
7978 		// power off the displays at state 0. At state 0 the root
7979 		// domain is removed from the wrangler's power client list.
7980 		if (wrangler) {
7981 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
7982 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
7983 		}
7984 	}
7985 }
7986 
7987 //******************************************************************************
7988 // dispatchPowerEvent
7989 //
7990 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
7991 //******************************************************************************
7992 
7993 void
7994 IOPMrootDomain::dispatchPowerEvent(
7995 	uint32_t event, void * arg0, uint64_t arg1 )
7996 {
7997 	ASSERT_GATED();
7998 
7999 	switch (event) {
8000 	case kPowerEventFeatureChanged:
8001 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8002 		messageClients(kIOPMMessageFeatureChange, this);
8003 		break;
8004 
8005 	case kPowerEventReceivedPowerNotification:
8006 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8007 		handlePowerNotification((UInt32)(uintptr_t) arg0 );
8008 		break;
8009 
8010 	case kPowerEventSystemBootCompleted:
8011 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8012 		if (systemBooting) {
8013 			systemBooting = false;
8014 
8015 			if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8016 				DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8017 			}
8018 			if (lowBatteryCondition || thermalEmergencyState) {
8019 				if (lowBatteryCondition) {
8020 					privateSleepSystem(kIOPMSleepReasonLowPower);
8021 				} else {
8022 					privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8023 				}
8024 				// The rest is unnecessary since the system is expected
8025 				// to sleep immediately. The following wake will update
8026 				// everything.
8027 				break;
8028 			}
8029 
8030 			sleepWakeDebugMemAlloc();
8031 			saveFailureData2File();
8032 
8033 			// If lid is closed, re-send lid closed notification
8034 			// now that booting is complete.
8035 			if (clamshellClosed) {
8036 				handlePowerNotification(kLocalEvalClamshellCommand);
8037 			}
8038 			evaluatePolicy( kStimulusAllowSystemSleepChanged );
8039 		}
8040 		break;
8041 
8042 	case kPowerEventSystemShutdown:
8043 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8044 		if (kOSBooleanTrue == (OSBoolean *) arg0) {
8045 			/* We set systemShutdown = true during shutdown
8046 			 *  to prevent sleep at unexpected times while loginwindow is trying
8047 			 *  to shutdown apps and while the OS is trying to transition to
8048 			 *  complete power of.
8049 			 *
8050 			 *  Set to true during shutdown, as soon as loginwindow shows
8051 			 *  the "shutdown countdown dialog", through individual app
8052 			 *  termination, and through black screen kernel shutdown.
8053 			 */
8054 			systemShutdown = true;
8055 		} else {
8056 			/*
8057 			 *  A shutdown was initiated, but then the shutdown
8058 			 *  was cancelled, clearing systemShutdown to false here.
8059 			 */
8060 			systemShutdown = false;
8061 		}
8062 		break;
8063 
8064 	case kPowerEventUserDisabledSleep:
8065 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8066 		userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8067 		break;
8068 
8069 	case kPowerEventRegisterSystemCapabilityClient:
8070 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8071 
8072 		// reset() handles the arg0 == nullptr case for us
8073 		systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8074 		/* intentional fall-through */
8075 		[[clang::fallthrough]];
8076 
8077 	case kPowerEventRegisterKernelCapabilityClient:
8078 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8079 		if (!_joinedCapabilityClients) {
8080 			_joinedCapabilityClients = OSSet::withCapacity(8);
8081 		}
8082 		if (arg0) {
8083 			OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8084 			if (_joinedCapabilityClients) {
8085 				_joinedCapabilityClients->setObject(notify.get());
8086 				synchronizePowerTree( kIOPMSyncNoChildNotify );
8087 			}
8088 		}
8089 		break;
8090 
8091 	case kPowerEventPolicyStimulus:
8092 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8093 		if (arg0) {
8094 			int stimulus = (int)(uintptr_t) arg0;
8095 			evaluatePolicy(stimulus, (uint32_t) arg1);
8096 		}
8097 		break;
8098 
8099 	case kPowerEventAssertionCreate:
8100 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8101 		if (pmAssertions) {
8102 			pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8103 		}
8104 		break;
8105 
8106 
8107 	case kPowerEventAssertionRelease:
8108 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8109 		if (pmAssertions) {
8110 			pmAssertions->handleReleaseAssertion(arg1);
8111 		}
8112 		break;
8113 
8114 	case kPowerEventAssertionSetLevel:
8115 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8116 		if (pmAssertions) {
8117 			pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8118 		}
8119 		break;
8120 
8121 	case kPowerEventQueueSleepWakeUUID:
8122 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8123 		handleQueueSleepWakeUUID((OSObject *)arg0);
8124 		break;
8125 	case kPowerEventPublishSleepWakeUUID:
8126 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8127 		handlePublishSleepWakeUUID((bool)arg0);
8128 		break;
8129 
8130 	case kPowerEventSetDisplayPowerOn:
8131 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8132 		if (arg1 != 0) {
8133 			displayPowerOnRequested = true;
8134 		} else {
8135 			displayPowerOnRequested = false;
8136 		}
8137 		handleSetDisplayPowerOn(displayPowerOnRequested);
8138 		break;
8139 
8140 	case kPowerEventPublishWakeType:
8141 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8142 
8143 		// Don't replace wake type property if already set
8144 		if ((arg0 == gIOPMWakeTypeUserKey) ||
8145 		    !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8146 			const char * wakeType = NULL;
8147 
8148 			if (arg0 == gIOPMWakeTypeUserKey) {
8149 				requestUserActive(this, "WakeTypeUser");
8150 				wakeType = kIOPMRootDomainWakeTypeUser;
8151 			} else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8152 				if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8153 					requestUserActive(this, "WakeTypeAlarm");
8154 				}
8155 				wakeType = kIOPMRootDomainWakeTypeAlarm;
8156 			} else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8157 				darkWakeSleepService = true;
8158 				wakeType = kIOPMRootDomainWakeTypeSleepService;
8159 			} else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8160 				wakeType = kIOPMRootDomainWakeTypeMaintenance;
8161 			}
8162 
8163 			if (wakeType) {
8164 				setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8165 			}
8166 		}
8167 		break;
8168 
8169 	case kPowerEventAOTEvaluate:
8170 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8171 		if (_aotReadyToFullWake) {
8172 			aotEvaluate(NULL);
8173 		}
8174 		break;
8175 	}
8176 }
8177 
8178 //******************************************************************************
8179 // systemPowerEventOccurred
8180 //
8181 // The power controller is notifying us of a hardware-related power management
8182 // event that we must handle.
8183 //
8184 // systemPowerEventOccurred covers the same functionality that
8185 // receivePowerNotification does; it simply provides a richer API for conveying
8186 // more information.
8187 //******************************************************************************
8188 
8189 IOReturn
8190 IOPMrootDomain::systemPowerEventOccurred(
8191 	const OSSymbol *event,
8192 	uint32_t intValue)
8193 {
8194 	IOReturn        attempt = kIOReturnSuccess;
8195 	OSSharedPtr<OSNumber>        newNumber;
8196 
8197 	if (!event) {
8198 		return kIOReturnBadArgument;
8199 	}
8200 
8201 	newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8202 	if (!newNumber) {
8203 		return kIOReturnInternalError;
8204 	}
8205 
8206 	attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8207 
8208 	return attempt;
8209 }
8210 
8211 void
8212 IOPMrootDomain::setThermalState(OSObject *value)
8213 {
8214 	OSNumber * num;
8215 
8216 	if (gIOPMWorkLoop->inGate() == false) {
8217 		gIOPMWorkLoop->runAction(
8218 			OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8219 			(OSObject *)this,
8220 			(void *)value);
8221 
8222 		return;
8223 	}
8224 	if (value && (num = OSDynamicCast(OSNumber, value))) {
8225 		thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8226 		    (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8227 	}
8228 }
8229 
8230 IOReturn
8231 IOPMrootDomain::systemPowerEventOccurred(
8232 	const OSSymbol *event,
8233 	OSObject *value)
8234 {
8235 	OSSharedPtr<OSDictionary> thermalsDict;
8236 	bool shouldUpdate = true;
8237 
8238 	if (!event || !value) {
8239 		return kIOReturnBadArgument;
8240 	}
8241 
8242 	// LOCK
8243 	// We reuse featuresDict Lock because it already exists and guards
8244 	// the very infrequently used publish/remove feature mechanism; so there's zero rsk
8245 	// of stepping on that lock.
8246 	if (featuresDictLock) {
8247 		IOLockLock(featuresDictLock);
8248 	}
8249 
8250 	OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8251 	OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8252 
8253 	if (origThermalsDict) {
8254 		thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8255 	} else {
8256 		thermalsDict = OSDictionary::withCapacity(1);
8257 	}
8258 
8259 	if (!thermalsDict) {
8260 		shouldUpdate = false;
8261 		goto exit;
8262 	}
8263 
8264 	thermalsDict->setObject(event, value);
8265 
8266 	setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8267 
8268 exit:
8269 	// UNLOCK
8270 	if (featuresDictLock) {
8271 		IOLockUnlock(featuresDictLock);
8272 	}
8273 
8274 	if (shouldUpdate) {
8275 		if (event &&
8276 		    event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8277 			setThermalState(value);
8278 		}
8279 		messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8280 	}
8281 
8282 	return kIOReturnSuccess;
8283 }
8284 
8285 //******************************************************************************
8286 // receivePowerNotification
8287 //
8288 // The power controller is notifying us of a hardware-related power management
8289 // event that we must handle. This may be a result of an 'environment' interrupt
8290 // from the power mgt micro.
8291 //******************************************************************************
8292 
8293 IOReturn
8294 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8295 {
8296 	if (msg & kIOPMPowerButton) {
8297 		uint32_t currentPhase = pmTracer->getTracePhase();
8298 		if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8299 			DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8300 			swd_flags |= SWD_PWR_BTN_STACKSHOT;
8301 			thread_call_enter(powerButtonDown);
8302 		} else {
8303 			DEBUG_LOG("power button pressed when system is up\n");
8304 		}
8305 	} else if (msg & kIOPMPowerButtonUp) {
8306 		if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8307 			swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8308 			thread_call_enter(powerButtonUp);
8309 		}
8310 	} else {
8311 		pmPowerStateQueue->submitPowerEvent(
8312 			kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8313 	}
8314 	return kIOReturnSuccess;
8315 }
8316 
8317 void
8318 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8319 {
8320 	bool        eval_clamshell = false;
8321 	bool        eval_clamshell_alarm = false;
8322 
8323 	ASSERT_GATED();
8324 
8325 	/*
8326 	 * Local (IOPMrootDomain only) eval clamshell command
8327 	 */
8328 	if (msg & kLocalEvalClamshellCommand) {
8329 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8330 			eval_clamshell_alarm = true;
8331 
8332 			// reset isRTCAlarmWake. This evaluation should happen only once
8333 			// on RTC/Alarm wake. Any clamshell events after wake should follow
8334 			// the regular evaluation
8335 			isRTCAlarmWake = false;
8336 		} else {
8337 			eval_clamshell = true;
8338 		}
8339 	}
8340 
8341 	/*
8342 	 * Overtemp
8343 	 */
8344 	if (msg & kIOPMOverTemp) {
8345 		DLOG("Thermal overtemp message received!\n");
8346 		thermalEmergencyState = true;
8347 		privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8348 	}
8349 
8350 	/*
8351 	 * Forward DW thermal notification to client, if system is not going to sleep
8352 	 */
8353 	if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8354 		DLOG("DarkWake thermal limits message received!\n");
8355 		messageClients(kIOPMMessageDarkWakeThermalEmergency);
8356 	}
8357 
8358 	/*
8359 	 * Sleep Now!
8360 	 */
8361 	if (msg & kIOPMSleepNow) {
8362 		privateSleepSystem(kIOPMSleepReasonSoftware);
8363 	}
8364 
8365 	/*
8366 	 * Power Emergency
8367 	 */
8368 	if (msg & kIOPMPowerEmergency) {
8369 		DLOG("Received kIOPMPowerEmergency");
8370 		lowBatteryCondition = true;
8371 		privateSleepSystem(kIOPMSleepReasonLowPower);
8372 	}
8373 
8374 	/*
8375 	 * Clamshell OPEN
8376 	 */
8377 	if (msg & kIOPMClamshellOpened) {
8378 		DLOG("Clamshell opened\n");
8379 		// Received clamshel open message from clamshell controlling driver
8380 		// Update our internal state and tell general interest clients
8381 		clamshellClosed = false;
8382 		clamshellExists = true;
8383 
8384 		// Don't issue a hid tickle when lid is open and polled on wake
8385 		if (msg & kIOPMSetValue) {
8386 			setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8387 			reportUserInput();
8388 		}
8389 
8390 		// Tell PMCPU
8391 		informCPUStateChange(kInformLid, 0);
8392 
8393 		// Tell general interest clients
8394 		sendClientClamshellNotification();
8395 
8396 		bool aborting =  ((lastSleepReason == kIOPMSleepReasonClamshell)
8397 		    || (lastSleepReason == kIOPMSleepReasonIdle)
8398 		    || (lastSleepReason == kIOPMSleepReasonMaintenance));
8399 		if (aborting) {
8400 			userActivityCount++;
8401 		}
8402 		DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8403 	}
8404 
8405 	/*
8406 	 * Clamshell CLOSED
8407 	 * Send the clamshell interest notification since the lid is closing.
8408 	 */
8409 	if (msg & kIOPMClamshellClosed) {
8410 		if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8411 		    clamshellClosed && clamshellExists) {
8412 			DLOG("Ignoring redundant Clamshell close event\n");
8413 		} else {
8414 			DLOG("Clamshell closed\n");
8415 			// Received clamshel open message from clamshell controlling driver
8416 			// Update our internal state and tell general interest clients
8417 			clamshellClosed = true;
8418 			clamshellExists = true;
8419 
8420 			// Ignore all following clamshell close events until the clamshell
8421 			// is opened or the system sleeps. When a clamshell close triggers
8422 			// a system wake, the lid driver may send us two clamshell close
8423 			// events, one for the clamshell close event itself, and a second
8424 			// close event when the driver polls the lid state on wake.
8425 			clamshellIgnoreClose = true;
8426 
8427 			// Tell PMCPU
8428 			informCPUStateChange(kInformLid, 1);
8429 
8430 			// Tell general interest clients
8431 			sendClientClamshellNotification();
8432 
8433 			// And set eval_clamshell = so we can attempt
8434 			eval_clamshell = true;
8435 		}
8436 	}
8437 
8438 	/*
8439 	 * Set Desktop mode (sent from graphics)
8440 	 *
8441 	 *  -> reevaluate lid state
8442 	 */
8443 	if (msg & kIOPMSetDesktopMode) {
8444 		desktopMode = (0 != (msg & kIOPMSetValue));
8445 		msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8446 		DLOG("Desktop mode %d\n", desktopMode);
8447 
8448 		sendClientClamshellNotification();
8449 
8450 		// Re-evaluate the lid state
8451 		eval_clamshell = true;
8452 	}
8453 
8454 	/*
8455 	 * AC Adaptor connected
8456 	 *
8457 	 *  -> reevaluate lid state
8458 	 */
8459 	if (msg & kIOPMSetACAdaptorConnected) {
8460 		acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8461 		msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8462 
8463 		// Tell CPU PM
8464 		informCPUStateChange(kInformAC, !acAdaptorConnected);
8465 
8466 		// Tell BSD if AC is connected
8467 		//      0 == external power source; 1 == on battery
8468 		post_sys_powersource(acAdaptorConnected ? 0:1);
8469 
8470 		sendClientClamshellNotification();
8471 
8472 		IOUserServer::powerSourceChanged(acAdaptorConnected);
8473 
8474 		// Re-evaluate the lid state
8475 		eval_clamshell = true;
8476 
8477 		// Lack of AC may have latched a display wrangler tickle.
8478 		// This mirrors the hardware's USB wake event latch, where a latched
8479 		// USB wake event followed by an AC attach will trigger a full wake.
8480 		latchDisplayWranglerTickle( false );
8481 
8482 #if HIBERNATION
8483 		// AC presence will reset the standy timer delay adjustment.
8484 		_standbyTimerResetSeconds = 0;
8485 #endif
8486 		if (!userIsActive) {
8487 			// Reset userActivityTime when power supply is changed(rdr 13789330)
8488 			clock_get_uptime(&userActivityTime);
8489 		}
8490 	}
8491 
8492 	/*
8493 	 * Enable Clamshell (external display disappear)
8494 	 *
8495 	 *  -> reevaluate lid state
8496 	 */
8497 	if (msg & kIOPMEnableClamshell) {
8498 		DLOG("Clamshell enabled\n");
8499 
8500 		// Re-evaluate the lid state
8501 		// System should sleep on external display disappearance
8502 		// in lid closed operation.
8503 		if (true == clamshellDisabled) {
8504 			eval_clamshell = true;
8505 
8506 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8507 			// Also clear kClamshellSleepDisableInternal when graphics enables
8508 			// the clamshell during a full wake. When graphics is behaving as
8509 			// expected, this will allow clamshell close to be honored earlier
8510 			// rather than waiting for the delayed evaluation.
8511 			if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8512 			    (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8513 			    CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8514 				setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8515 
8516 				// Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8517 				// when timer expires which is harmless but useless.
8518 				thread_call_cancel(fullWakeThreadCall);
8519 			}
8520 #endif
8521 		}
8522 
8523 		clamshellDisabled = false;
8524 		sendClientClamshellNotification();
8525 	}
8526 
8527 	/*
8528 	 * Disable Clamshell (external display appeared)
8529 	 * We don't bother re-evaluating clamshell state. If the system is awake,
8530 	 * the lid is probably open.
8531 	 */
8532 	if (msg & kIOPMDisableClamshell) {
8533 		DLOG("Clamshell disabled\n");
8534 		clamshellDisabled = true;
8535 		sendClientClamshellNotification();
8536 	}
8537 
8538 	/*
8539 	 * Evaluate clamshell and SLEEP if appropriate
8540 	 */
8541 	if (eval_clamshell_alarm && clamshellClosed) {
8542 		if (shouldSleepOnRTCAlarmWake()) {
8543 			privateSleepSystem(kIOPMSleepReasonClamshell);
8544 		}
8545 	} else if (eval_clamshell && clamshellClosed) {
8546 		if (shouldSleepOnClamshellClosed()) {
8547 			privateSleepSystem(kIOPMSleepReasonClamshell);
8548 		} else {
8549 			evaluatePolicy( kStimulusDarkWakeEvaluate );
8550 		}
8551 	}
8552 
8553 	if (msg & kIOPMProModeEngaged) {
8554 		int newState = 1;
8555 		DLOG("ProModeEngaged\n");
8556 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8557 	}
8558 
8559 	if (msg & kIOPMProModeDisengaged) {
8560 		int newState = 0;
8561 		DLOG("ProModeDisengaged\n");
8562 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8563 	}
8564 }
8565 
8566 //******************************************************************************
8567 // evaluatePolicy
8568 //
8569 // Evaluate root-domain policy in response to external changes.
8570 //******************************************************************************
8571 
8572 void
8573 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8574 {
8575 	union {
8576 		struct {
8577 			int idleSleepEnabled    : 1;
8578 			int idleSleepDisabled   : 1;
8579 			int displaySleep        : 1;
8580 			int sleepDelayChanged   : 1;
8581 			int evaluateDarkWake    : 1;
8582 			int adjustPowerState    : 1;
8583 			int userBecameInactive  : 1;
8584 			int displaySleepEntry   : 1;
8585 		} bit;
8586 		uint32_t u32;
8587 	} flags;
8588 
8589 
8590 	ASSERT_GATED();
8591 	flags.u32 = 0;
8592 
8593 	switch (stimulus) {
8594 	case kStimulusDisplayWranglerSleep:
8595 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8596 		if (!wranglerPowerOff) {
8597 			// wrangler is in sleep state or lower
8598 			flags.bit.displaySleep = true;
8599 		}
8600 		if (!wranglerAsleep) {
8601 			// transition from wrangler wake to wrangler sleep
8602 			flags.bit.displaySleepEntry = true;
8603 			wranglerAsleep = true;
8604 		}
8605 		break;
8606 
8607 	case kStimulusDisplayWranglerWake:
8608 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8609 		displayIdleForDemandSleep = false;
8610 		wranglerPowerOff = false;
8611 		wranglerAsleep = false;
8612 		break;
8613 
8614 	case kStimulusEnterUserActiveState:
8615 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8616 		if (_preventUserActive) {
8617 			DLOG("user active dropped\n");
8618 			break;
8619 		}
8620 		if (!userIsActive) {
8621 			userIsActive = true;
8622 			userWasActive = true;
8623 			clock_get_uptime(&gUserActiveAbsTime);
8624 
8625 			// Stay awake after dropping demand for display power on
8626 			if (kFullWakeReasonDisplayOn == fullWakeReason) {
8627 				fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8628 				DLOG("User activity while in notification wake\n");
8629 				changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8630 			}
8631 
8632 			kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8633 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8634 			messageClients(kIOPMMessageUserIsActiveChanged);
8635 		}
8636 		flags.bit.idleSleepDisabled = true;
8637 		break;
8638 
8639 	case kStimulusLeaveUserActiveState:
8640 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8641 		if (userIsActive) {
8642 			clock_get_uptime(&gUserInactiveAbsTime);
8643 			userIsActive = false;
8644 			clock_get_uptime(&userBecameInactiveTime);
8645 			flags.bit.userBecameInactive = true;
8646 
8647 			kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8648 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8649 			messageClients(kIOPMMessageUserIsActiveChanged);
8650 		}
8651 		break;
8652 
8653 	case kStimulusAggressivenessChanged:
8654 	{
8655 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8656 		unsigned long   aggressiveValue;
8657 		uint32_t        minutesToIdleSleep  = 0;
8658 		uint32_t        minutesToDisplayDim = 0;
8659 		uint32_t        minutesDelta        = 0;
8660 
8661 		// Fetch latest display and system sleep slider values.
8662 		aggressiveValue = 0;
8663 		getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
8664 		minutesToIdleSleep = (uint32_t) aggressiveValue;
8665 
8666 		aggressiveValue = 0;
8667 		getAggressiveness(kPMMinutesToDim, &aggressiveValue);
8668 		minutesToDisplayDim = (uint32_t) aggressiveValue;
8669 		DLOG("aggressiveness changed: system %u->%u, display %u\n",
8670 		    sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
8671 
8672 		DLOG("idle time -> %d ms (ena %d)\n",
8673 		    idleMilliSeconds, (minutesToIdleSleep != 0));
8674 
8675 		// How long to wait before sleeping the system once
8676 		// the displays turns off is indicated by 'extraSleepDelay'.
8677 
8678 		if (minutesToIdleSleep > minutesToDisplayDim) {
8679 			minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
8680 		} else if (minutesToIdleSleep == minutesToDisplayDim) {
8681 			minutesDelta = 1;
8682 		}
8683 
8684 		if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
8685 			idleSleepEnabled = flags.bit.idleSleepEnabled = true;
8686 		}
8687 
8688 		if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
8689 			flags.bit.idleSleepDisabled = true;
8690 			idleSleepEnabled = false;
8691 		}
8692 #if !defined(XNU_TARGET_OS_OSX)
8693 		if (0x7fffffff == minutesToIdleSleep) {
8694 			minutesToIdleSleep = idleMilliSeconds / 1000;
8695 		}
8696 #endif /* !defined(XNU_TARGET_OS_OSX) */
8697 
8698 		if (((minutesDelta != extraSleepDelay) ||
8699 		    (userActivityTime != userActivityTime_prev)) &&
8700 		    !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
8701 			flags.bit.sleepDelayChanged = true;
8702 		}
8703 
8704 		if (systemDarkWake && !darkWakeToSleepASAP &&
8705 		    (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
8706 			// Reconsider decision to remain in dark wake
8707 			flags.bit.evaluateDarkWake = true;
8708 		}
8709 
8710 		sleepSlider = minutesToIdleSleep;
8711 		extraSleepDelay = minutesDelta;
8712 		userActivityTime_prev = userActivityTime;
8713 	}   break;
8714 
8715 	case kStimulusDemandSystemSleep:
8716 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8717 		displayIdleForDemandSleep = true;
8718 		if (wrangler && wranglerIdleSettings) {
8719 			// Request wrangler idle only when demand sleep is triggered
8720 			// from full wake.
8721 			if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8722 				wrangler->setProperties(wranglerIdleSettings.get());
8723 				DLOG("Requested wrangler idle\n");
8724 			}
8725 		}
8726 		// arg = sleepReason
8727 		changePowerStateWithOverrideTo( SLEEP_STATE, arg );
8728 		break;
8729 
8730 	case kStimulusAllowSystemSleepChanged:
8731 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8732 		flags.bit.adjustPowerState = true;
8733 		break;
8734 
8735 	case kStimulusDarkWakeActivityTickle:
8736 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8737 		// arg == true implies real and not self generated wrangler tickle.
8738 		// Update wake type on PM work loop instead of the tickle thread to
8739 		// eliminate the possibility of an early tickle clobbering the wake
8740 		// type set by the platform driver.
8741 		if (arg == true) {
8742 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
8743 		}
8744 
8745 		if (!darkWakeExit) {
8746 			if (latchDisplayWranglerTickle(true)) {
8747 				DLOG("latched tickle\n");
8748 				break;
8749 			}
8750 
8751 			darkWakeExit = true;
8752 			DLOG("Requesting full wake due to dark wake activity tickle\n");
8753 			requestFullWake( kFullWakeReasonLocalUser );
8754 		}
8755 		break;
8756 
8757 	case kStimulusDarkWakeEntry:
8758 	case kStimulusDarkWakeReentry:
8759 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8760 		// Any system transitions since the last dark wake transition
8761 		// will invalid the stimulus.
8762 
8763 		if (arg == _systemStateGeneration) {
8764 			DLOG("dark wake entry\n");
8765 			systemDarkWake = true;
8766 
8767 			// Keep wranglerPowerOff an invariant when wrangler is absent
8768 			if (wrangler) {
8769 				wranglerPowerOff = true;
8770 			}
8771 
8772 			if (kStimulusDarkWakeEntry == stimulus) {
8773 				clock_get_uptime(&userBecameInactiveTime);
8774 				flags.bit.evaluateDarkWake = true;
8775 				if (activitySinceSleep()) {
8776 					DLOG("User activity recorded while going to darkwake\n");
8777 					reportUserInput();
8778 				}
8779 			}
8780 
8781 			// Always accelerate disk spindown while in dark wake,
8782 			// even if system does not support/allow sleep.
8783 
8784 			cancelIdleSleepTimer();
8785 			setQuickSpinDownTimeout();
8786 		}
8787 		break;
8788 
8789 	case kStimulusDarkWakeEvaluate:
8790 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8791 		if (systemDarkWake) {
8792 			flags.bit.evaluateDarkWake = true;
8793 		}
8794 		break;
8795 
8796 	case kStimulusNoIdleSleepPreventers:
8797 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8798 		flags.bit.adjustPowerState = true;
8799 		break;
8800 	} /* switch(stimulus) */
8801 
8802 	if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
8803 		DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
8804 		    darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
8805 		if (darkWakeToSleepASAP ||
8806 		    (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
8807 			uint32_t newSleepReason;
8808 
8809 			if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
8810 				// System was previously in full wake. Sleep reason from
8811 				// full to dark already recorded in fullToDarkReason.
8812 
8813 				if (lowBatteryCondition) {
8814 					newSleepReason = kIOPMSleepReasonLowPower;
8815 				} else if (thermalEmergencyState) {
8816 					newSleepReason = kIOPMSleepReasonThermalEmergency;
8817 				} else {
8818 					newSleepReason = fullToDarkReason;
8819 				}
8820 			} else {
8821 				// In dark wake from system sleep.
8822 
8823 				if (darkWakeSleepService) {
8824 					newSleepReason = kIOPMSleepReasonSleepServiceExit;
8825 				} else {
8826 					newSleepReason = kIOPMSleepReasonMaintenance;
8827 				}
8828 			}
8829 
8830 			if (checkSystemCanSleep(newSleepReason)) {
8831 				privateSleepSystem(newSleepReason);
8832 			}
8833 		} else { // non-maintenance (network) dark wake
8834 			if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
8835 				// Release power clamp, and wait for children idle.
8836 				adjustPowerState(true);
8837 			} else {
8838 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
8839 			}
8840 		}
8841 	}
8842 
8843 	if (systemDarkWake) {
8844 		// The rest are irrelevant while system is in dark wake.
8845 		flags.u32 = 0;
8846 	}
8847 
8848 	if ((flags.bit.displaySleepEntry) &&
8849 	    (kFullWakeReasonDisplayOn == fullWakeReason)) {
8850 		// kIOPMSleepReasonNotificationWakeExit
8851 		DLOG("Display sleep while in notification wake\n");
8852 		changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
8853 	}
8854 
8855 	if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
8856 		bool cancelQuickSpindown = false;
8857 
8858 		if (flags.bit.sleepDelayChanged) {
8859 			// Cancel existing idle sleep timer and quick disk spindown.
8860 			// New settings will be applied by the idleSleepEnabled flag
8861 			// handler below if idle sleep is enabled.
8862 
8863 			DLOG("extra sleep timer changed\n");
8864 			cancelIdleSleepTimer();
8865 			cancelQuickSpindown = true;
8866 		} else {
8867 			DLOG("user inactive\n");
8868 		}
8869 
8870 		if (!userIsActive && idleSleepEnabled) {
8871 			startIdleSleepTimer(getTimeToIdleSleep());
8872 		}
8873 
8874 		if (cancelQuickSpindown) {
8875 			restoreUserSpinDownTimeout();
8876 		}
8877 	}
8878 
8879 	if (flags.bit.idleSleepEnabled) {
8880 		DLOG("idle sleep timer enabled\n");
8881 		if (!wrangler) {
8882 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8883 			startIdleSleepTimer(getTimeToIdleSleep());
8884 #else
8885 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
8886 			startIdleSleepTimer( idleMilliSeconds );
8887 #endif
8888 		} else {
8889 			// Start idle timer if prefs now allow system sleep
8890 			// and user is already inactive. Disk spindown is
8891 			// accelerated upon timer expiration.
8892 
8893 			if (!userIsActive) {
8894 				startIdleSleepTimer(getTimeToIdleSleep());
8895 			}
8896 		}
8897 	}
8898 
8899 	if (flags.bit.idleSleepDisabled) {
8900 		DLOG("idle sleep timer disabled\n");
8901 		cancelIdleSleepTimer();
8902 		restoreUserSpinDownTimeout();
8903 		adjustPowerState();
8904 	}
8905 
8906 	if (flags.bit.adjustPowerState) {
8907 		bool sleepASAP = false;
8908 
8909 		if (!systemBooting && (0 == idleSleepPreventersCount())) {
8910 			if (!wrangler) {
8911 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
8912 				if (idleSleepEnabled) {
8913 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
8914 					if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
8915 						sleepASAP = true;
8916 					}
8917 #else
8918 					// stay awake for at least idleMilliSeconds
8919 					startIdleSleepTimer(idleMilliSeconds);
8920 #endif
8921 				}
8922 			} else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
8923 				sleepASAP = true;
8924 			}
8925 		}
8926 
8927 		adjustPowerState(sleepASAP);
8928 	}
8929 }
8930 
8931 //******************************************************************************
8932 
8933 unsigned int
8934 IOPMrootDomain::idleSleepPreventersCount()
8935 {
8936 	if (_aotMode) {
8937 		unsigned int count __block;
8938 		count = 0;
8939 		preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
8940 		{
8941 			count += (NULL == obj->metaCast("AppleARMBacklight"));
8942 			return false;
8943 		});
8944 		return count;
8945 	}
8946 
8947 	return preventIdleSleepList->getCount();
8948 }
8949 
8950 
8951 //******************************************************************************
8952 // requestFullWake
8953 //
8954 // Request transition from dark wake to full wake
8955 //******************************************************************************
8956 
8957 void
8958 IOPMrootDomain::requestFullWake( FullWakeReason reason )
8959 {
8960 	uint32_t        options = 0;
8961 	IOService *     pciRoot = NULL;
8962 	bool            promotion = false;
8963 
8964 	// System must be in dark wake and a valid reason for entering full wake
8965 	if ((kFullWakeReasonNone == reason) ||
8966 	    (kFullWakeReasonNone != fullWakeReason) ||
8967 	    (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8968 		return;
8969 	}
8970 
8971 	// Will clear reason upon exit from full wake
8972 	fullWakeReason = reason;
8973 
8974 	_desiredCapability |= (kIOPMSystemCapabilityGraphics |
8975 	    kIOPMSystemCapabilityAudio);
8976 
8977 	if ((kSystemTransitionWake == _systemTransitionType) &&
8978 	    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
8979 	    !darkWakePowerClamped) {
8980 		// Promote to full wake while waking up to dark wake due to tickle.
8981 		// PM will hold off notifying the graphics subsystem about system wake
8982 		// as late as possible, so if a HID tickle does arrive, graphics can
8983 		// power up from this same wake transition. Otherwise, the latency to
8984 		// power up graphics on the following transition can be huge on certain
8985 		// systems. However, once any power clamping has taken effect, it is
8986 		// too late to promote the current dark wake transition to a full wake.
8987 		_pendingCapability |= (kIOPMSystemCapabilityGraphics |
8988 		    kIOPMSystemCapabilityAudio);
8989 
8990 		// Tell the PCI parent of audio and graphics drivers to stop
8991 		// delaying the child notifications. Same for root domain.
8992 		pciRoot = pciHostBridgeDriver.get();
8993 		willEnterFullWake();
8994 		promotion = true;
8995 	}
8996 
8997 	// Unsafe to cancel once graphics was powered.
8998 	// If system woke from dark wake, the return to sleep can
8999 	// be cancelled. "awake -> dark -> sleep" transition
9000 	// can be cancelled also, during the "dark -> sleep" phase
9001 	// *prior* to driver power down.
9002 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9003 	    _pendingCapability == 0) {
9004 		options |= kIOPMSyncCancelPowerDown;
9005 	}
9006 
9007 	synchronizePowerTree(options, pciRoot);
9008 
9009 	if (kFullWakeReasonLocalUser == fullWakeReason) {
9010 		// IOGraphics doesn't light the display even though graphics is
9011 		// enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9012 		// So, do an explicit activity tickle
9013 		if (wrangler) {
9014 			wrangler->activityTickle(0, 0);
9015 		}
9016 	}
9017 
9018 	// Log a timestamp for the initial full wake request.
9019 	// System may not always honor this full wake request.
9020 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9021 		AbsoluteTime    now;
9022 		uint64_t        nsec;
9023 
9024 		clock_get_uptime(&now);
9025 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9026 		absolutetime_to_nanoseconds(now, &nsec);
9027 		MSG("full wake %s (reason %u) %u ms\n",
9028 		    promotion ? "promotion" : "request",
9029 		    fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9030 	}
9031 }
9032 
9033 //******************************************************************************
9034 // willEnterFullWake
9035 //
9036 // System will enter full wake from sleep, from dark wake, or from dark
9037 // wake promotion. This function aggregate things that are in common to
9038 // all three full wake transitions.
9039 //
9040 // Assumptions: fullWakeReason was updated
9041 //******************************************************************************
9042 
9043 void
9044 IOPMrootDomain::willEnterFullWake( void )
9045 {
9046 	hibernateRetry = false;
9047 	sleepToStandby = false;
9048 	standbyNixed   = false;
9049 	resetTimers    = false;
9050 	sleepTimerMaintenance = false;
9051 
9052 	assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9053 
9054 	_systemMessageClientMask = kSystemMessageClientPowerd |
9055 	    kSystemMessageClientLegacyApp;
9056 
9057 	if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9058 		// First time to attain full wake capability since the last wake
9059 		_systemMessageClientMask |= kSystemMessageClientKernel;
9060 
9061 		// Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9062 		setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9063 		    (kFullWakeReasonLocalUser == fullWakeReason) ?
9064 		    kOSBooleanTrue : kOSBooleanFalse);
9065 	}
9066 #if HIBERNATION
9067 	IOHibernateSetWakeCapabilities(_pendingCapability);
9068 #endif
9069 
9070 	IOService::setAdvisoryTickleEnable( true );
9071 	tellClients(kIOMessageSystemWillPowerOn);
9072 	preventTransitionToUserActive(false);
9073 }
9074 
9075 //******************************************************************************
9076 // fullWakeDelayedWork
9077 //
9078 // System has already entered full wake. Invoked by a delayed thread call.
9079 //******************************************************************************
9080 
9081 void
9082 IOPMrootDomain::fullWakeDelayedWork( void )
9083 {
9084 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9085 	if (!gIOPMWorkLoop->inGate()) {
9086 		gIOPMWorkLoop->runAction(
9087 			OSMemberFunctionCast(IOWorkLoop::Action, this,
9088 			&IOPMrootDomain::fullWakeDelayedWork), this);
9089 		return;
9090 	}
9091 
9092 	DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9093 	    _currentCapability, _pendingCapability, _highestCapability,
9094 	    clamshellDisabled, clamshellSleepDisableMask);
9095 
9096 	if (clamshellExists &&
9097 	    CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9098 	    !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9099 		if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9100 			setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9101 		} else {
9102 			// Not the initial full wake after waking from sleep.
9103 			// Evaluate the clamshell for rdar://problem/9157444.
9104 			receivePowerNotification(kLocalEvalClamshellCommand);
9105 		}
9106 	}
9107 #endif
9108 }
9109 
9110 //******************************************************************************
9111 // evaluateAssertions
9112 //
9113 //******************************************************************************
9114 
9115 // Bitmask of all kernel assertions that prevent system idle sleep.
9116 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9117 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9118 	(kIOPMDriverAssertionReservedBit7 | \
9119 	 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9120 
9121 void
9122 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9123 {
9124 	IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9125 
9126 	messageClients(kIOPMMessageDriverAssertionsChanged);
9127 
9128 	if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9129 		if (wrangler) {
9130 			bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9131 
9132 			DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9133 			wrangler->setIgnoreIdleTimer( value );
9134 		}
9135 	}
9136 
9137 	if (changedBits & kIOPMDriverAssertionCPUBit) {
9138 		if (_aotNow) {
9139 			IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9140 		}
9141 		evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9142 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9143 			AbsoluteTime    now;
9144 			clock_usec_t    microsecs;
9145 			clock_get_uptime(&now);
9146 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9147 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
9148 			if (assertOnWakeReport) {
9149 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9150 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9151 			}
9152 		}
9153 	}
9154 
9155 	if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9156 		if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9157 			if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9158 				DLOG("PreventIdleSleep driver assertion raised\n");
9159 				bool ok = updatePreventIdleSleepList(this, true);
9160 				if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9161 					// Cancel idle sleep if there is one in progress
9162 					cancelIdlePowerDown(this);
9163 				}
9164 			}
9165 		} else {
9166 			DLOG("PreventIdleSleep driver assertion dropped\n");
9167 			updatePreventIdleSleepList(this, false);
9168 		}
9169 	}
9170 }
9171 
9172 // MARK: -
9173 // MARK: Statistics
9174 
9175 //******************************************************************************
9176 // pmStats
9177 //
9178 //******************************************************************************
9179 
9180 void
9181 IOPMrootDomain::pmStatsRecordEvent(
9182 	int                 eventIndex,
9183 	AbsoluteTime        timestamp)
9184 {
9185 	bool        starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9186 	bool        stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9187 	uint64_t    delta;
9188 	uint64_t    nsec;
9189 	OSSharedPtr<OSData> publishPMStats;
9190 
9191 	eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9192 
9193 	absolutetime_to_nanoseconds(timestamp, &nsec);
9194 
9195 	switch (eventIndex) {
9196 	case kIOPMStatsHibernateImageWrite:
9197 		if (starting) {
9198 			gPMStats.hibWrite.start = nsec;
9199 		} else if (stopping) {
9200 			gPMStats.hibWrite.stop = nsec;
9201 		}
9202 
9203 		if (stopping) {
9204 			delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9205 			IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9206 		}
9207 		break;
9208 	case kIOPMStatsHibernateImageRead:
9209 		if (starting) {
9210 			gPMStats.hibRead.start = nsec;
9211 		} else if (stopping) {
9212 			gPMStats.hibRead.stop = nsec;
9213 		}
9214 
9215 		if (stopping) {
9216 			delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9217 			IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9218 
9219 			publishPMStats = OSData::withValue(gPMStats);
9220 			setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9221 			bzero(&gPMStats, sizeof(gPMStats));
9222 		}
9223 		break;
9224 	}
9225 }
9226 
9227 /*
9228  * Appends a record of the application response to
9229  * IOPMrootDomain::pmStatsAppResponses
9230  */
9231 void
9232 IOPMrootDomain::pmStatsRecordApplicationResponse(
9233 	const OSSymbol      *response,
9234 	const char          *name,
9235 	int                 messageType,
9236 	uint32_t            delay_ms,
9237 	uint64_t            id,
9238 	OSObject            *object,
9239 	IOPMPowerStateIndex powerState,
9240 	bool                async)
9241 {
9242 	OSSharedPtr<OSDictionary>    responseDescription;
9243 	OSSharedPtr<OSNumber>        delayNum;
9244 	OSSharedPtr<OSNumber>        powerCaps;
9245 	OSSharedPtr<OSNumber>        pidNum;
9246 	OSSharedPtr<OSNumber>        msgNum;
9247 	OSSharedPtr<const OSSymbol>  appname;
9248 	OSSharedPtr<const OSSymbol>  sleep;
9249 	OSSharedPtr<const OSSymbol>  wake;
9250 	IOPMServiceInterestNotifier *notify = NULL;
9251 
9252 	if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9253 		if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9254 			notify->ackTimeoutCnt++;
9255 		} else {
9256 			notify->ackTimeoutCnt = 0;
9257 		}
9258 	}
9259 
9260 	if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9261 	    (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9262 		return;
9263 	}
9264 
9265 
9266 	if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9267 		kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9268 	} else if (notify) {
9269 		// User space app or kernel capability client
9270 		if (id) {
9271 			kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9272 		} else {
9273 			kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9274 		}
9275 		notify->msgType = 0;
9276 	}
9277 
9278 	responseDescription = OSDictionary::withCapacity(5);
9279 	if (responseDescription) {
9280 		if (response) {
9281 			responseDescription->setObject(_statsResponseTypeKey.get(), response);
9282 		}
9283 
9284 		msgNum = OSNumber::withNumber(messageType, 32);
9285 		if (msgNum) {
9286 			responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9287 		}
9288 
9289 		if (!name && notify && notify->identifier) {
9290 			name = notify->identifier->getCStringNoCopy();
9291 		}
9292 
9293 		if (name && (strlen(name) > 0)) {
9294 			appname = OSSymbol::withCString(name);
9295 			if (appname) {
9296 				responseDescription->setObject(_statsNameKey.get(), appname.get());
9297 			}
9298 		}
9299 
9300 		if (!id && notify) {
9301 			id = notify->uuid0;
9302 		}
9303 		pidNum = OSNumber::withNumber(id, 64);
9304 		if (pidNum) {
9305 			responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9306 		}
9307 
9308 		delayNum = OSNumber::withNumber(delay_ms, 32);
9309 		if (delayNum) {
9310 			responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9311 		}
9312 
9313 		if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9314 			powerCaps = OSNumber::withNumber(powerState, 32);
9315 
9316 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9317 			static const char * driverCallTypes[] = {
9318 				[kDriverCallInformPreChange]  = "powerStateWillChangeTo",
9319 				[kDriverCallInformPostChange] = "powerStateDidChangeTo",
9320 				[kDriverCallSetPowerState]    = "setPowerState"
9321 			};
9322 
9323 			if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9324 				DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9325 				    name, id, driverCallTypes[messageType], (uint32_t) powerState,
9326 				    async ? "async " : "", delay_ms);
9327 			}
9328 #endif
9329 		} else {
9330 			powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9331 		}
9332 		if (powerCaps) {
9333 			responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9334 		}
9335 
9336 		sleep = OSSymbol::withCString("Sleep");
9337 		wake = OSSymbol::withCString("Wake");
9338 		if (_systemTransitionType == kSystemTransitionSleep) {
9339 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9340 		} else if (_systemTransitionType == kSystemTransitionWake) {
9341 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9342 		} else if (_systemTransitionType == kSystemTransitionCapability) {
9343 			if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9344 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9345 			} else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9346 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9347 			}
9348 		}
9349 
9350 		IOLockLock(pmStatsLock);
9351 		if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9352 			pmStatsAppResponses->setObject(responseDescription.get());
9353 		}
9354 		IOLockUnlock(pmStatsLock);
9355 	}
9356 
9357 	return;
9358 }
9359 
9360 // MARK: -
9361 // MARK: PMTraceWorker
9362 
9363 //******************************************************************************
9364 // TracePoint support
9365 //
9366 //******************************************************************************
9367 
9368 #define kIOPMRegisterNVRAMTracePointHandlerKey  \
9369 	"IOPMRegisterNVRAMTracePointHandler"
9370 
9371 IOReturn
9372 IOPMrootDomain::callPlatformFunction(
9373 	const OSSymbol * functionName,
9374 	bool waitForFunction,
9375 	void * param1, void * param2,
9376 	void * param3, void * param4 )
9377 {
9378 	if (pmTracer && functionName &&
9379 	    functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9380 	    !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9381 		uint32_t    tracePointPhases, tracePointPCI;
9382 		uint64_t    statusCode;
9383 
9384 		pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9385 		pmTracer->tracePointTarget  = (void *) param2;
9386 		tracePointPCI               = (uint32_t)(uintptr_t) param3;
9387 		tracePointPhases            = (uint32_t)(uintptr_t) param4;
9388 		if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9389 			OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9390 			if (node) {
9391 				OSSharedPtr<OSObject> bootRomFailureProp;
9392 				bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9393 				OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9394 				uint32_t bootFailureCode;
9395 				if (data && data->getLength() == sizeof(bootFailureCode)) {
9396 					// Failure code from EFI/BootRom is a four byte structure
9397 					memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9398 					tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9399 				}
9400 			}
9401 		}
9402 		statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9403 		if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9404 			MSG("Sleep failure code 0x%08x 0x%08x\n",
9405 			    tracePointPCI, tracePointPhases);
9406 		}
9407 		setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9408 		pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9409 
9410 		return kIOReturnSuccess;
9411 	}
9412 #if HIBERNATION
9413 	else if (functionName &&
9414 	    functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9415 		if (gSleepPolicyHandler) {
9416 			return kIOReturnExclusiveAccess;
9417 		}
9418 		if (!param1) {
9419 			return kIOReturnBadArgument;
9420 		}
9421 		gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9422 		gSleepPolicyTarget  = (void *) param2;
9423 		setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9424 		return kIOReturnSuccess;
9425 	}
9426 #endif
9427 
9428 	return super::callPlatformFunction(
9429 		functionName, waitForFunction, param1, param2, param3, param4);
9430 }
9431 
9432 void
9433 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9434     uintptr_t param1, uintptr_t param2, uintptr_t param3)
9435 {
9436 	uint32_t code   = IODBG_POWER(event);
9437 	uint64_t regId  = id;
9438 	if (regId == 0) {
9439 		regId  = getRegistryEntryID();
9440 	}
9441 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9442 }
9443 
9444 void
9445 IOPMrootDomain::tracePoint( uint8_t point )
9446 {
9447 	if (systemBooting) {
9448 		return;
9449 	}
9450 
9451 	if (kIOPMTracePointWakeCapabilityClients == point) {
9452 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9453 	}
9454 
9455 	kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9456 	pmTracer->tracePoint(point);
9457 }
9458 
9459 static void
9460 kext_log_putc(char c)
9461 {
9462 	if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9463 		return;
9464 	}
9465 	if (c == '(' || c == '[' || c == ' ') {
9466 		c = 0;
9467 		gKextNameEnd = true;
9468 	}
9469 
9470 	gKextNameBuf[gKextNamePos++] = c;
9471 }
9472 
9473 static int
9474 kext_log(const char *fmt, ...)
9475 {
9476 	va_list listp;
9477 
9478 	va_start(listp, fmt);
9479 	_doprnt(fmt, &listp, &kext_log_putc, 16);
9480 	va_end(listp);
9481 
9482 	return 0;
9483 }
9484 
9485 static OSPtr<const OSSymbol>
9486 copyKextIdentifierWithAddress(vm_address_t address)
9487 {
9488 	OSSharedPtr<const OSSymbol> identifer;
9489 
9490 	IOLockLock(gHaltLogLock);
9491 
9492 	gKextNameEnd = false;
9493 	gKextNamePos = 0;
9494 	gKextNameBuf[0] = 0;
9495 
9496 	OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9497 	gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9498 	identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9499 
9500 	IOLockUnlock(gHaltLogLock);
9501 
9502 	return identifer;
9503 }
9504 
9505 // Caller serialized using PM workloop
9506 const char *
9507 IOPMrootDomain::getNotificationClientName(OSObject *object)
9508 {
9509 	IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9510 	const char *clientName = "UNKNOWN";
9511 
9512 	if (!notifier->clientName) {
9513 		// Check for user client
9514 		if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9515 			OSNumber *clientID = NULL;
9516 			messageClient(kIOMessageCopyClientID, object, &clientID);
9517 			if (clientID) {
9518 				OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9519 				if (string) {
9520 					notifier->clientName = OSSymbol::withString(string.get());
9521 				}
9522 				clientID->release();
9523 			}
9524 		} else if (notifier->identifier) {
9525 			notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9526 		}
9527 	}
9528 
9529 	if (notifier->clientName) {
9530 		clientName = notifier->clientName->getCStringNoCopy();
9531 	}
9532 
9533 	return clientName;
9534 }
9535 
9536 void
9537 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9538 {
9539 	IOPMServiceInterestNotifier *notifier;
9540 
9541 	if (systemBooting) {
9542 		return;
9543 	}
9544 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9545 	if (!notifier) {
9546 		return;
9547 	}
9548 
9549 	if (start) {
9550 		pmTracer->traceDetail(notifier->uuid0 >> 32);
9551 		kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9552 		    (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9553 
9554 		// Update notifier state used for response/ack logging
9555 		notifier->msgIndex = msgIndex;
9556 		notifier->msgAbsTime = timestamp;
9557 
9558 		if (msgIndex != UINT_MAX) {
9559 			DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9560 		} else {
9561 			DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9562 		}
9563 
9564 		assert(notifierObject == NULL);
9565 		notifierThread = current_thread();
9566 		notifierObject.reset(notifier, OSRetain);
9567 	} else {
9568 		uint64_t nsec;
9569 		uint32_t delayMS;
9570 
9571 		SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9572 		absolutetime_to_nanoseconds(timestamp, &nsec);
9573 		delayMS = (uint32_t)(nsec / 1000000ULL);
9574 		if (delayMS > notifier->maxMsgDelayMS) {
9575 			notifier->maxMsgDelayMS = delayMS;
9576 		}
9577 
9578 		assert(notifierObject == notifier);
9579 		notifierObject.reset();
9580 		notifierThread = NULL;
9581 	}
9582 }
9583 
9584 void
9585 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9586 {
9587 	if (systemBooting) {
9588 		return;
9589 	}
9590 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9591 	if (!notifier) {
9592 		return;
9593 	}
9594 
9595 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9596 	    (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9597 
9598 	DLOG("%s[%u] ack from %s took %d ms\n",
9599 	    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9600 	if (delay_ms > notifier->maxAckDelayMS) {
9601 		notifier->maxAckDelayMS = delay_ms;
9602 	}
9603 }
9604 
9605 void
9606 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9607 {
9608 	if (systemBooting) {
9609 		return;
9610 	}
9611 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9612 	if (!notifier) {
9613 		return;
9614 	}
9615 
9616 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9617 	    (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9618 
9619 	if (ack_time_us == 0) {
9620 		// Client work is done and ack will not be forthcoming
9621 		DLOG("%s[%u] response from %s took %d ms\n",
9622 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9623 	} else {
9624 		// Client needs more time and it must ack within ack_time_us
9625 		DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9626 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9627 	}
9628 }
9629 
9630 void
9631 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9632 {
9633 	if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9634 		return;
9635 	}
9636 	if (systemBooting) {
9637 		return;
9638 	}
9639 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9640 	if (!notifier) {
9641 		return;
9642 	}
9643 
9644 	DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9645 }
9646 
9647 void
9648 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9649 {
9650 	if (!systemBooting) {
9651 		uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
9652 		pmTracer->traceDetail( detail );
9653 		kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
9654 		DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
9655 	}
9656 }
9657 
9658 void
9659 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
9660 {
9661 	size_t      reportSize;
9662 	void        **report = NULL;
9663 	uint32_t    bktCnt;
9664 	uint32_t    bktSize;
9665 	uint32_t    *clientCnt;
9666 
9667 	ASSERT_GATED();
9668 
9669 	report = NULL;
9670 	if (channel_id == kAssertDelayChID) {
9671 		report = &assertOnWakeReport;
9672 		bktCnt = kAssertDelayBcktCnt;
9673 		bktSize = kAssertDelayBcktSize;
9674 		clientCnt = &assertOnWakeClientCnt;
9675 	} else if (channel_id == kSleepDelaysChID) {
9676 		report = &sleepDelaysReport;
9677 		bktCnt = kSleepDelaysBcktCnt;
9678 		bktSize = kSleepDelaysBcktSize;
9679 		clientCnt = &sleepDelaysClientCnt;
9680 	} else {
9681 		assert(false);
9682 		return;
9683 	}
9684 
9685 	switch (action) {
9686 	case kIOReportEnable:
9687 
9688 		if (*report) {
9689 			(*clientCnt)++;
9690 			break;
9691 		}
9692 
9693 		reportSize = HISTREPORT_BUFSIZE(bktCnt);
9694 		*report = IOMallocZeroData(reportSize);
9695 		if (*report == NULL) {
9696 			break;
9697 		}
9698 		HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
9699 		    getRegistryEntryID(), channel_id, kIOReportCategoryPower);
9700 
9701 		if (channel_id == kAssertDelayChID) {
9702 			assertOnWakeSecs = 0;
9703 		}
9704 
9705 		break;
9706 
9707 	case kIOReportDisable:
9708 		if (*clientCnt == 0) {
9709 			break;
9710 		}
9711 		if (*clientCnt == 1) {
9712 			IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
9713 			*report = NULL;
9714 		}
9715 		(*clientCnt)--;
9716 
9717 		if (channel_id == kAssertDelayChID) {
9718 			assertOnWakeSecs = -1; // Invalid value to prevent updates
9719 		}
9720 		break;
9721 
9722 	case kIOReportGetDimensions:
9723 		if (*report) {
9724 			HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
9725 		}
9726 		break;
9727 	}
9728 
9729 	return;
9730 }
9731 
9732 IOReturn
9733 IOPMrootDomain::configureReport(IOReportChannelList    *channelList,
9734     IOReportConfigureAction action,
9735     void                   *result,
9736     void                   *destination)
9737 {
9738 	unsigned cnt;
9739 	uint64_t configAction = (uint64_t)action;
9740 
9741 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9742 		if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
9743 		    (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
9744 		    (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
9745 			if (action != kIOReportGetDimensions) {
9746 				continue;
9747 			}
9748 			SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
9749 		} else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
9750 		    (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
9751 			gIOPMWorkLoop->runAction(
9752 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
9753 				(OSObject *)this, (void *)channelList->channels[cnt].channel_id,
9754 				(void *)configAction, (void *)result);
9755 		}
9756 	}
9757 
9758 	return super::configureReport(channelList, action, result, destination);
9759 }
9760 
9761 IOReturn
9762 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
9763 {
9764 	uint32_t    size2cpy;
9765 	void        *data2cpy;
9766 	void        **report;
9767 
9768 	ASSERT_GATED();
9769 
9770 	report = NULL;
9771 	if (ch_id == kAssertDelayChID) {
9772 		report = &assertOnWakeReport;
9773 	} else if (ch_id == kSleepDelaysChID) {
9774 		report = &sleepDelaysReport;
9775 	} else {
9776 		assert(false);
9777 		return kIOReturnBadArgument;
9778 	}
9779 
9780 	if (*report == NULL) {
9781 		return kIOReturnNotOpen;
9782 	}
9783 
9784 	HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
9785 	if (size2cpy > (dest->getCapacity() - dest->getLength())) {
9786 		return kIOReturnOverrun;
9787 	}
9788 
9789 	HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
9790 	dest->appendBytes(data2cpy, size2cpy);
9791 
9792 	return kIOReturnSuccess;
9793 }
9794 
9795 IOReturn
9796 IOPMrootDomain::updateReport(IOReportChannelList      *channelList,
9797     IOReportUpdateAction      action,
9798     void                     *result,
9799     void                     *destination)
9800 {
9801 	uint32_t size2cpy;
9802 	void *data2cpy;
9803 	uint8_t buf[SIMPLEREPORT_BUFSIZE];
9804 	IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
9805 	unsigned cnt;
9806 	uint64_t ch_id;
9807 
9808 	if (action != kIOReportCopyChannelData) {
9809 		goto exit;
9810 	}
9811 
9812 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
9813 		ch_id = channelList->channels[cnt].channel_id;
9814 
9815 		if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
9816 			gIOPMWorkLoop->runAction(
9817 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
9818 				(OSObject *)this, (void *)ch_id,
9819 				(void *)result, (void *)dest);
9820 			continue;
9821 		} else if ((ch_id == kSleepCntChID) ||
9822 		    (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
9823 			SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
9824 		} else {
9825 			continue;
9826 		}
9827 
9828 		if (ch_id == kSleepCntChID) {
9829 			SIMPLEREPORT_SETVALUE(buf, sleepCnt);
9830 		} else if (ch_id == kDarkWkCntChID) {
9831 			SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
9832 		} else if (ch_id == kUserWkCntChID) {
9833 			SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
9834 		}
9835 
9836 		SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
9837 		SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
9838 		dest->appendBytes(data2cpy, size2cpy);
9839 	}
9840 
9841 exit:
9842 	return super::updateReport(channelList, action, result, destination);
9843 }
9844 
9845 
9846 //******************************************************************************
9847 // PMTraceWorker Class
9848 //
9849 //******************************************************************************
9850 
9851 #undef super
9852 #define super OSObject
9853 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
9854 
9855 #define kPMBestGuessPCIDevicesCount     25
9856 #define kPMMaxRTCBitfieldSize           32
9857 
9858 OSPtr<PMTraceWorker>
9859 PMTraceWorker::tracer(IOPMrootDomain * owner)
9860 {
9861 	OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
9862 	if (!me || !me->init()) {
9863 		return NULL;
9864 	}
9865 
9866 	DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
9867 
9868 	// Note that we cannot instantiate the PCI device -> bit mappings here, since
9869 	// the IODeviceTree has not yet been created by IOPlatformExpert. We create
9870 	// this dictionary lazily.
9871 	me->owner = owner;
9872 	me->pciDeviceBitMappings = NULL;
9873 	me->pmTraceWorkerLock = IOLockAlloc();
9874 	me->tracePhase = kIOPMTracePointSystemUp;
9875 	me->traceData32 = 0;
9876 	me->loginWindowData = 0;
9877 	me->coreDisplayData = 0;
9878 	me->coreGraphicsData = 0;
9879 	return me;
9880 }
9881 
9882 void
9883 PMTraceWorker::RTC_TRACE(void)
9884 {
9885 	if (tracePointHandler && tracePointTarget) {
9886 		uint32_t    wordA;
9887 
9888 		IOLockLock(pmTraceWorkerLock);
9889 		wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
9890 		    (coreGraphicsData << 8) | tracePhase;
9891 		IOLockUnlock(pmTraceWorkerLock);
9892 
9893 		tracePointHandler( tracePointTarget, traceData32, wordA );
9894 		_LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
9895 	}
9896 #if DEVELOPMENT || DEBUG
9897 	if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
9898 		DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
9899 		IOLock *l = IOLockAlloc();
9900 		IOLockLock(l);
9901 		IOLockLock(l);
9902 	}
9903 #endif /* DEVELOPMENT || DEBUG */
9904 }
9905 
9906 int
9907 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
9908 {
9909 	OSSharedPtr<const OSSymbol>    deviceName;
9910 	int                 index = -1;
9911 
9912 	IOLockLock(pmTraceWorkerLock);
9913 
9914 	if (!pciDeviceBitMappings) {
9915 		pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
9916 		if (!pciDeviceBitMappings) {
9917 			goto exit;
9918 		}
9919 	}
9920 
9921 	// Check for bitmask overflow.
9922 	if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
9923 		goto exit;
9924 	}
9925 
9926 	if ((deviceName = pciDevice->copyName()) &&
9927 	    (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
9928 	    pciDeviceBitMappings->setObject(deviceName.get())) {
9929 		index = pciDeviceBitMappings->getCount() - 1;
9930 		_LOG("PMTrace PCI array: set object %s => %d\n",
9931 		    deviceName->getCStringNoCopy(), index);
9932 	}
9933 
9934 	if (!addedToRegistry && (index >= 0)) {
9935 		addedToRegistry = owner->setProperty("PCITopLevel", this);
9936 	}
9937 
9938 exit:
9939 	IOLockUnlock(pmTraceWorkerLock);
9940 	return index;
9941 }
9942 
9943 bool
9944 PMTraceWorker::serialize(OSSerialize *s) const
9945 {
9946 	bool ok = false;
9947 	if (pciDeviceBitMappings) {
9948 		IOLockLock(pmTraceWorkerLock);
9949 		ok = pciDeviceBitMappings->serialize(s);
9950 		IOLockUnlock(pmTraceWorkerLock);
9951 	}
9952 	return ok;
9953 }
9954 
9955 void
9956 PMTraceWorker::tracePoint(uint8_t phase)
9957 {
9958 	// clear trace detail when phase begins
9959 	if (tracePhase != phase) {
9960 		traceData32 = 0;
9961 	}
9962 
9963 	tracePhase = phase;
9964 
9965 	DLOG("trace point 0x%02x\n", tracePhase);
9966 	RTC_TRACE();
9967 }
9968 
9969 void
9970 PMTraceWorker::traceDetail(uint32_t detail)
9971 {
9972 	if (detail == traceData32) {
9973 		return;
9974 	}
9975 	traceData32 = detail;
9976 	RTC_TRACE();
9977 }
9978 
9979 void
9980 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
9981 {
9982 	switch (component) {
9983 	case kIOPMLoginWindowProgress:
9984 		loginWindowData = data & kIOPMLoginWindowProgressMask;
9985 		break;
9986 	case kIOPMCoreDisplayProgress:
9987 		coreDisplayData = data & kIOPMCoreDisplayProgressMask;
9988 		break;
9989 	case kIOPMCoreGraphicsProgress:
9990 		coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
9991 		break;
9992 	default:
9993 		return;
9994 	}
9995 
9996 	DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
9997 	RTC_TRACE();
9998 }
9999 
10000 void
10001 PMTraceWorker::tracePCIPowerChange(
10002 	change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10003 {
10004 	uint32_t    bitMask;
10005 	uint32_t    expectedFlag;
10006 
10007 	// Ignore PCI changes outside of system sleep/wake.
10008 	if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10009 	    (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10010 		return;
10011 	}
10012 
10013 	// Only record the WillChange transition when going to sleep,
10014 	// and the DidChange on the way up.
10015 	changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10016 	expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10017 	    kIOPMDomainWillChange : kIOPMDomainDidChange;
10018 	if (changeFlags != expectedFlag) {
10019 		return;
10020 	}
10021 
10022 	// Mark this device off in our bitfield
10023 	if (bitNum < kPMMaxRTCBitfieldSize) {
10024 		bitMask = (1 << bitNum);
10025 
10026 		if (kPowerChangeStart == type) {
10027 			traceData32 |= bitMask;
10028 			_LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n",
10029 			    service->getName(), bitNum, bitMask, traceData32);
10030 			owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10031 		} else {
10032 			traceData32 &= ~bitMask;
10033 			_LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10034 			    service->getName(), bitNum, bitMask, traceData32);
10035 			owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10036 		}
10037 
10038 		DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10039 		RTC_TRACE();
10040 	}
10041 }
10042 
10043 uint64_t
10044 PMTraceWorker::getPMStatusCode()
10045 {
10046 	return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10047 }
10048 
10049 uint8_t
10050 PMTraceWorker::getTracePhase()
10051 {
10052 	return tracePhase;
10053 }
10054 
10055 uint32_t
10056 PMTraceWorker::getTraceData()
10057 {
10058 	return traceData32;
10059 }
10060 
10061 // MARK: -
10062 // MARK: PMHaltWorker
10063 
10064 //******************************************************************************
10065 // PMHaltWorker Class
10066 //
10067 //******************************************************************************
10068 
10069 PMHaltWorker *
10070 PMHaltWorker::worker( void )
10071 {
10072 	PMHaltWorker *  me;
10073 	IOThread        thread;
10074 
10075 	do {
10076 		me = OSTypeAlloc( PMHaltWorker );
10077 		if (!me || !me->init()) {
10078 			break;
10079 		}
10080 
10081 		me->lock = IOLockAlloc();
10082 		if (!me->lock) {
10083 			break;
10084 		}
10085 
10086 		DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10087 		me->retain(); // thread holds extra retain
10088 		if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10089 			me->release();
10090 			break;
10091 		}
10092 		thread_deallocate(thread);
10093 		return me;
10094 	} while (false);
10095 
10096 	if (me) {
10097 		me->release();
10098 	}
10099 	return NULL;
10100 }
10101 
10102 void
10103 PMHaltWorker::free( void )
10104 {
10105 	DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10106 	if (lock) {
10107 		IOLockFree(lock);
10108 		lock = NULL;
10109 	}
10110 	return OSObject::free();
10111 }
10112 
10113 void
10114 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10115 {
10116 	PMHaltWorker * me = (PMHaltWorker *) arg;
10117 
10118 	IOLockLock( gPMHaltLock );
10119 	gPMHaltBusyCount++;
10120 	me->depth = gPMHaltDepth;
10121 	IOLockUnlock( gPMHaltLock );
10122 
10123 	while (me->depth >= 0) {
10124 		PMHaltWorker::work( me );
10125 
10126 		IOLockLock( gPMHaltLock );
10127 		if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10128 			// This is the last thread to finish work on this level,
10129 			// inform everyone to start working on next lower level.
10130 			gPMHaltDepth--;
10131 			me->depth = gPMHaltDepth;
10132 			gPMHaltIdleCount = 0;
10133 			thread_wakeup((event_t) &gPMHaltIdleCount);
10134 		} else {
10135 			// One or more threads are still working on this level,
10136 			// this thread must wait.
10137 			me->depth = gPMHaltDepth - 1;
10138 			do {
10139 				IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10140 			} while (me->depth != gPMHaltDepth);
10141 		}
10142 		IOLockUnlock( gPMHaltLock );
10143 	}
10144 
10145 	// No more work to do, terminate thread
10146 	DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10147 	thread_wakeup( &gPMHaltDepth );
10148 	me->release();
10149 }
10150 
10151 void
10152 PMHaltWorker::work( PMHaltWorker * me )
10153 {
10154 	OSSharedPtr<IOService>     service;
10155 	OSSet *         inner;
10156 	AbsoluteTime    startTime, elapsedTime;
10157 	UInt32          deltaTime;
10158 	bool            timeout;
10159 
10160 	while (true) {
10161 		timeout = false;
10162 
10163 		// Claim an unit of work from the shared pool
10164 		IOLockLock( gPMHaltLock );
10165 		inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10166 		if (inner) {
10167 			service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10168 			if (service) {
10169 				inner->removeObject(service.get());
10170 			}
10171 		}
10172 		IOLockUnlock( gPMHaltLock );
10173 		if (!service) {
10174 			break; // no more work at this depth
10175 		}
10176 		clock_get_uptime(&startTime);
10177 
10178 		if (!service->isInactive() &&
10179 		    service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10180 			IOLockLock(me->lock);
10181 			me->startTime = startTime;
10182 			me->service   = service.get();
10183 			me->timeout   = false;
10184 			IOLockUnlock(me->lock);
10185 
10186 			service->systemWillShutdown( gPMHaltMessageType);
10187 
10188 			// Wait for driver acknowledgement
10189 			IOLockLock(me->lock);
10190 			while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10191 				IOLockSleep(me->lock, me, THREAD_UNINT);
10192 			}
10193 			me->service = NULL;
10194 			timeout = me->timeout;
10195 			IOLockUnlock(me->lock);
10196 		}
10197 
10198 		deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10199 		if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10200 			LOG("%s driver %s (0x%llx) took %u ms\n",
10201 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10202 			    "PowerOff" : "Restart",
10203 			    service->getName(), service->getRegistryEntryID(),
10204 			    (uint32_t) deltaTime );
10205 			halt_log_enter("PowerOff/Restart handler completed",
10206 			    OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10207 			    elapsedTime);
10208 		}
10209 
10210 		me->visits++;
10211 	}
10212 }
10213 
10214 void
10215 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10216 {
10217 	UInt64          nano;
10218 	AbsoluteTime    startTime;
10219 	AbsoluteTime    endTime;
10220 
10221 	endTime = *now;
10222 
10223 	IOLockLock(me->lock);
10224 	if (me->service && !me->timeout) {
10225 		startTime = me->startTime;
10226 		nano = 0;
10227 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10228 			SUB_ABSOLUTETIME(&endTime, &startTime);
10229 			absolutetime_to_nanoseconds(endTime, &nano);
10230 		}
10231 		if (nano > 3000000000ULL) {
10232 			me->timeout = true;
10233 
10234 			halt_log_enter("PowerOff/Restart still waiting on handler",
10235 			    OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10236 			    endTime);
10237 			MSG("%s still waiting on %s\n",
10238 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?  "PowerOff" : "Restart",
10239 			    me->service->getName());
10240 		}
10241 	}
10242 	IOLockUnlock(me->lock);
10243 }
10244 
10245 //******************************************************************************
10246 // acknowledgeSystemWillShutdown
10247 //
10248 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10249 //******************************************************************************
10250 
10251 void
10252 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10253 {
10254 	PMHaltWorker            * worker;
10255 	OSSharedPtr<OSObject>     prop;
10256 
10257 	if (!from) {
10258 		return;
10259 	}
10260 
10261 	//DLOG("%s acknowledged\n", from->getName());
10262 	prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10263 	if (prop) {
10264 		worker = (PMHaltWorker *) prop.get();
10265 		IOLockLock(worker->lock);
10266 		from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10267 		thread_wakeup((event_t) worker);
10268 		IOLockUnlock(worker->lock);
10269 	} else {
10270 		DLOG("%s acknowledged without worker property\n",
10271 		    from->getName());
10272 	}
10273 }
10274 
10275 
10276 //******************************************************************************
10277 // notifySystemShutdown
10278 //
10279 // Notify all objects in PM tree that system will shutdown or restart
10280 //******************************************************************************
10281 
10282 static void
10283 notifySystemShutdown( IOService * root, uint32_t messageType )
10284 {
10285 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10286 	OSSharedPtr<IORegistryIterator>  iter;
10287 	IORegistryEntry *                entry;
10288 	IOService *                      node;
10289 	OSSet *                          inner;
10290 	OSSharedPtr<OSSet>               newInner;
10291 	PMHaltWorker *                   workers[kPMHaltMaxWorkers];
10292 	AbsoluteTime                     deadline;
10293 	unsigned int                     totalNodes = 0;
10294 	unsigned int                     depth;
10295 	unsigned int                     rootDepth;
10296 	unsigned int                     numWorkers;
10297 	unsigned int                     count;
10298 	int                              waitResult;
10299 	void *                           baseFunc;
10300 	bool                             ok;
10301 
10302 	DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10303 
10304 	baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10305 
10306 	// Iterate the entire PM tree starting from root
10307 
10308 	rootDepth = root->getDepth( gIOPowerPlane );
10309 	if (!rootDepth) {
10310 		goto done;
10311 	}
10312 
10313 	// debug - for repeated test runs
10314 	while (PMHaltWorker::metaClass->getInstanceCount()) {
10315 		IOSleep(1);
10316 	}
10317 
10318 	if (!gPMHaltArray) {
10319 		gPMHaltArray = OSArray::withCapacity(40);
10320 		if (!gPMHaltArray) {
10321 			goto done;
10322 		}
10323 	} else { // debug
10324 		gPMHaltArray->flushCollection();
10325 	}
10326 
10327 	if (!gPMHaltLock) {
10328 		gPMHaltLock = IOLockAlloc();
10329 		if (!gPMHaltLock) {
10330 			goto done;
10331 		}
10332 	}
10333 
10334 	if (!gPMHaltClientAcknowledgeKey) {
10335 		gPMHaltClientAcknowledgeKey =
10336 		    OSSymbol::withCStringNoCopy("PMShutdown");
10337 		if (!gPMHaltClientAcknowledgeKey) {
10338 			goto done;
10339 		}
10340 	}
10341 
10342 	gPMHaltMessageType = messageType;
10343 
10344 	// Depth-first walk of PM plane
10345 
10346 	iter = IORegistryIterator::iterateOver(
10347 		root, gIOPowerPlane, kIORegistryIterateRecursively);
10348 
10349 	if (iter) {
10350 		while ((entry = iter->getNextObject())) {
10351 			node = OSDynamicCast(IOService, entry);
10352 			if (!node) {
10353 				continue;
10354 			}
10355 
10356 			if (baseFunc ==
10357 			    OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10358 				continue;
10359 			}
10360 
10361 			depth = node->getDepth( gIOPowerPlane );
10362 			if (depth <= rootDepth) {
10363 				continue;
10364 			}
10365 
10366 			ok = false;
10367 
10368 			// adjust to zero based depth
10369 			depth -= (rootDepth + 1);
10370 
10371 			// gPMHaltArray is an array of containers, each container
10372 			// refers to nodes with the same depth.
10373 
10374 			count = gPMHaltArray->getCount();
10375 			while (depth >= count) {
10376 				// expand array and insert placeholders
10377 				gPMHaltArray->setObject(PLACEHOLDER);
10378 				count++;
10379 			}
10380 			count = gPMHaltArray->getCount();
10381 			if (depth < count) {
10382 				inner = (OSSet *)gPMHaltArray->getObject(depth);
10383 				if (inner == PLACEHOLDER) {
10384 					newInner = OSSet::withCapacity(40);
10385 					if (newInner) {
10386 						gPMHaltArray->replaceObject(depth, newInner.get());
10387 						inner = newInner.get();
10388 					}
10389 				}
10390 
10391 				// PM nodes that appear more than once in the tree will have
10392 				// the same depth, OSSet will refuse to add the node twice.
10393 				if (inner) {
10394 					ok = inner->setObject(node);
10395 				}
10396 			}
10397 			if (!ok) {
10398 				DLOG("Skipped PM node %s\n", node->getName());
10399 			}
10400 		}
10401 	}
10402 
10403 	// debug only
10404 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10405 		count = 0;
10406 		if (inner != PLACEHOLDER) {
10407 			count = inner->getCount();
10408 		}
10409 		DLOG("Nodes at depth %u = %u\n", i, count);
10410 	}
10411 
10412 	// strip placeholders (not all depths are populated)
10413 	numWorkers = 0;
10414 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10415 		if (inner == PLACEHOLDER) {
10416 			gPMHaltArray->removeObject(i);
10417 			continue;
10418 		}
10419 		count = inner->getCount();
10420 		if (count > numWorkers) {
10421 			numWorkers = count;
10422 		}
10423 		totalNodes += count;
10424 		i++;
10425 	}
10426 
10427 	if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10428 		goto done;
10429 	}
10430 
10431 	gPMHaltBusyCount = 0;
10432 	gPMHaltIdleCount = 0;
10433 	gPMHaltDepth = gPMHaltArray->getCount() - 1;
10434 
10435 	// Create multiple workers (and threads)
10436 
10437 	if (numWorkers > kPMHaltMaxWorkers) {
10438 		numWorkers = kPMHaltMaxWorkers;
10439 	}
10440 
10441 	DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10442 	    totalNodes, gPMHaltArray->getCount(), numWorkers);
10443 
10444 	for (unsigned int i = 0; i < numWorkers; i++) {
10445 		workers[i] = PMHaltWorker::worker();
10446 	}
10447 
10448 	// Wait for workers to exhaust all available work
10449 
10450 	IOLockLock(gPMHaltLock);
10451 	while (gPMHaltDepth >= 0) {
10452 		clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10453 
10454 		waitResult = IOLockSleepDeadline(
10455 			gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10456 		if (THREAD_TIMED_OUT == waitResult) {
10457 			AbsoluteTime now;
10458 			clock_get_uptime(&now);
10459 
10460 			IOLockUnlock(gPMHaltLock);
10461 			for (unsigned int i = 0; i < numWorkers; i++) {
10462 				if (workers[i]) {
10463 					PMHaltWorker::checkTimeout(workers[i], &now);
10464 				}
10465 			}
10466 			IOLockLock(gPMHaltLock);
10467 		}
10468 	}
10469 	IOLockUnlock(gPMHaltLock);
10470 
10471 	// Release all workers
10472 
10473 	for (unsigned int i = 0; i < numWorkers; i++) {
10474 		if (workers[i]) {
10475 			workers[i]->release();
10476 		}
10477 		// worker also retained by it's own thread
10478 	}
10479 
10480 done:
10481 	DLOG("%s done\n", __FUNCTION__);
10482 	return;
10483 }
10484 
10485 // MARK: -
10486 // MARK: Kernel Assertion
10487 
10488 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10489 
10490 IOPMDriverAssertionID
10491 IOPMrootDomain::createPMAssertion(
10492 	IOPMDriverAssertionType whichAssertionBits,
10493 	IOPMDriverAssertionLevel assertionLevel,
10494 	IOService *ownerService,
10495 	const char *ownerDescription)
10496 {
10497 	IOReturn            ret;
10498 	IOPMDriverAssertionID     newAssertion;
10499 
10500 	if (!pmAssertions) {
10501 		return 0;
10502 	}
10503 
10504 	ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10505 
10506 	if (kIOReturnSuccess == ret) {
10507 #if (DEVELOPMENT || DEBUG)
10508 		if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10509 			OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion, ownerService->getName(), ownerDescription);
10510 		}
10511 #endif /* (DEVELOPMENT || DEBUG) */
10512 		return newAssertion;
10513 	} else {
10514 		return 0;
10515 	}
10516 }
10517 
10518 IOReturn
10519 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10520 {
10521 #if (DEVELOPMENT || DEBUG)
10522 	if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10523 		PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10524 		if (details && details->ownerService && details->ownerString) {
10525 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion,
10526 			    details->ownerService->getName(), details->ownerString->getCStringNoCopy());
10527 		} else {
10528 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10529 		}
10530 	}
10531 #endif /* (DEVELOPMENT || DEBUG) */
10532 	if (!pmAssertions) {
10533 		return kIOReturnInternalError;
10534 	}
10535 	return pmAssertions->releaseAssertion(releaseAssertion);
10536 }
10537 
10538 
10539 IOReturn
10540 IOPMrootDomain::setPMAssertionLevel(
10541 	IOPMDriverAssertionID assertionID,
10542 	IOPMDriverAssertionLevel assertionLevel)
10543 {
10544 	return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10545 }
10546 
10547 IOPMDriverAssertionLevel
10548 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10549 {
10550 	IOPMDriverAssertionType       sysLevels;
10551 
10552 	if (!pmAssertions || whichAssertion == 0) {
10553 		return kIOPMDriverAssertionLevelOff;
10554 	}
10555 
10556 	sysLevels = pmAssertions->getActivatedAssertions();
10557 
10558 	// Check that every bit set in argument 'whichAssertion' is asserted
10559 	// in the aggregate bits.
10560 	if ((sysLevels & whichAssertion) == whichAssertion) {
10561 		return kIOPMDriverAssertionLevelOn;
10562 	} else {
10563 		return kIOPMDriverAssertionLevelOff;
10564 	}
10565 }
10566 
10567 IOReturn
10568 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10569 {
10570 	if (!pmAssertions) {
10571 		return kIOReturnNotFound;
10572 	}
10573 
10574 	return pmAssertions->setUserAssertionLevels(inLevels);
10575 }
10576 
10577 IOReturn
10578 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10579 {
10580 	return gIOPMWorkLoop->runActionBlock(^{
10581 		if (_driverKitMatchingAssertionCount != 0) {
10582 		        _driverKitMatchingAssertionCount++;
10583 		        return kIOReturnSuccess;
10584 		} else {
10585 		        if (kSystemTransitionSleep == _systemTransitionType) {
10586 		                // system going to sleep
10587 		                return kIOReturnBusy;
10588 			} else {
10589 		                // createPMAssertion is asynchronous.
10590 		                // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10591 		                // The assertion is used so that on release, we reevaluate all assertions
10592 		                _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10593 		                if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10594 		                        _driverKitMatchingAssertionCount = 1;
10595 		                        return kIOReturnSuccess;
10596 				} else {
10597 		                        return kIOReturnBusy;
10598 				}
10599 			}
10600 		}
10601 	});
10602 }
10603 
10604 void
10605 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10606 {
10607 	gIOPMWorkLoop->runActionBlock(^{
10608 		if (_driverKitMatchingAssertionCount != 0) {
10609 		        _driverKitMatchingAssertionCount--;
10610 		        if (_driverKitMatchingAssertionCount == 0) {
10611 		                releasePMAssertion(_driverKitMatchingAssertion);
10612 		                _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10613 			}
10614 		} else {
10615 		        panic("Over-release of driverkit matching assertion");
10616 		}
10617 		return kIOReturnSuccess;
10618 	});
10619 }
10620 
10621 bool
10622 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
10623 {
10624 	if (pmAssertions) {
10625 		pmAssertions->publishProperties();
10626 	}
10627 	return IOService::serializeProperties(s);
10628 }
10629 
10630 OSSharedPtr<OSObject>
10631 IOPMrootDomain::copyProperty( const char * aKey) const
10632 {
10633 	OSSharedPtr<OSObject> obj;
10634 	obj = IOService::copyProperty(aKey);
10635 
10636 	if (obj) {
10637 		return obj;
10638 	}
10639 
10640 	if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
10641 	    sizeof(kIOPMSleepWakeWdogRebootKey))) {
10642 		if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
10643 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10644 		} else {
10645 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10646 		}
10647 	}
10648 
10649 	if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
10650 	    sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
10651 		if (swd_flags & SWD_VALID_LOGS) {
10652 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10653 		} else {
10654 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10655 		}
10656 	}
10657 
10658 	/*
10659 	 * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey'
10660 	 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
10661 	 * issued by DisplayWrangler on darkwake.
10662 	 */
10663 	if (!strcmp(aKey, "DesktopMode")) {
10664 		if (desktopMode) {
10665 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10666 		} else {
10667 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10668 		}
10669 	}
10670 	if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
10671 		if (displayIdleForDemandSleep) {
10672 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
10673 		} else {
10674 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
10675 		}
10676 	}
10677 
10678 	if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
10679 		OSSharedPtr<OSArray> array;
10680 		WAKEEVENT_LOCK();
10681 		if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
10682 			OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
10683 			if (collection) {
10684 				array = OSDynamicPtrCast<OSArray>(collection);
10685 			}
10686 		}
10687 		WAKEEVENT_UNLOCK();
10688 		return os::move(array);
10689 	}
10690 
10691 	if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
10692 		OSSharedPtr<OSArray> array;
10693 		IOLockLock(pmStatsLock);
10694 		if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
10695 			OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
10696 			if (collection) {
10697 				array = OSDynamicPtrCast<OSArray>(collection);
10698 			}
10699 		}
10700 		IOLockUnlock(pmStatsLock);
10701 		return os::move(array);
10702 	}
10703 
10704 	if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
10705 		OSArray *idleSleepList = NULL;
10706 		gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
10707 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10708 	}
10709 
10710 	if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
10711 		OSArray *systemSleepList = NULL;
10712 		gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
10713 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10714 	}
10715 
10716 	if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
10717 		OSArray *idleSleepList = NULL;
10718 		gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
10719 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
10720 	}
10721 
10722 	if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
10723 		OSArray *systemSleepList = NULL;
10724 		gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
10725 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
10726 	}
10727 	return NULL;
10728 }
10729 
10730 // MARK: -
10731 // MARK: Wake Event Reporting
10732 
10733 void
10734 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
10735 {
10736 	WAKEEVENT_LOCK();
10737 	strlcpy(outBuf, gWakeReasonString, bufSize);
10738 	WAKEEVENT_UNLOCK();
10739 }
10740 
10741 void
10742 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
10743 {
10744 	WAKEEVENT_LOCK();
10745 	strlcpy(outBuf, gShutdownReasonString, bufSize);
10746 	WAKEEVENT_UNLOCK();
10747 }
10748 
10749 //******************************************************************************
10750 // acceptSystemWakeEvents
10751 //
10752 // Private control for the acceptance of driver wake event claims.
10753 //******************************************************************************
10754 
10755 void
10756 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
10757 {
10758 	bool logWakeReason = false;
10759 
10760 	WAKEEVENT_LOCK();
10761 	switch (control) {
10762 	case kAcceptSystemWakeEvents_Enable:
10763 		assert(_acceptSystemWakeEvents == false);
10764 		if (!_systemWakeEventsArray) {
10765 			_systemWakeEventsArray = OSArray::withCapacity(4);
10766 		}
10767 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10768 		if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
10769 			gWakeReasonString[0] = '\0';
10770 			if (_systemWakeEventsArray) {
10771 				_systemWakeEventsArray->flushCollection();
10772 			}
10773 		}
10774 
10775 		// Remove stale WakeType property before system sleep
10776 		removeProperty(kIOPMRootDomainWakeTypeKey);
10777 		removeProperty(kIOPMRootDomainWakeReasonKey);
10778 		break;
10779 
10780 	case kAcceptSystemWakeEvents_Disable:
10781 		_acceptSystemWakeEvents = false;
10782 #if defined(XNU_TARGET_OS_OSX)
10783 		logWakeReason = (gWakeReasonString[0] != '\0');
10784 #else /* !defined(XNU_TARGET_OS_OSX) */
10785 		logWakeReason = gWakeReasonSysctlRegistered;
10786 #if DEVELOPMENT
10787 		static int panic_allowed = -1;
10788 
10789 		if ((panic_allowed == -1) &&
10790 		    (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
10791 			panic_allowed = 0;
10792 		}
10793 
10794 		if (panic_allowed) {
10795 			size_t i = 0;
10796 			// Panic if wake reason is null or empty
10797 			for (i = 0; (i < strlen(gWakeReasonString)); i++) {
10798 				if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
10799 					break;
10800 				}
10801 			}
10802 			if (i >= strlen(gWakeReasonString)) {
10803 				panic("Wake reason is empty");
10804 			}
10805 		}
10806 #endif /* DEVELOPMENT */
10807 #endif /* !defined(XNU_TARGET_OS_OSX) */
10808 
10809 		// publish kIOPMRootDomainWakeReasonKey if not already set
10810 		if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
10811 			setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
10812 		}
10813 		break;
10814 
10815 	case kAcceptSystemWakeEvents_Reenable:
10816 		assert(_acceptSystemWakeEvents == false);
10817 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
10818 		removeProperty(kIOPMRootDomainWakeReasonKey);
10819 		break;
10820 	}
10821 	WAKEEVENT_UNLOCK();
10822 
10823 	if (logWakeReason) {
10824 		MSG("system wake events: %s\n", gWakeReasonString);
10825 	}
10826 }
10827 
10828 //******************************************************************************
10829 // claimSystemWakeEvent
10830 //
10831 // For a driver to claim a device is the source/conduit of a system wake event.
10832 //******************************************************************************
10833 
10834 void
10835 IOPMrootDomain::claimSystemWakeEvent(
10836 	IOService *     device,
10837 	IOOptionBits    flags,
10838 	const char *    reason,
10839 	OSObject *      details )
10840 {
10841 	OSSharedPtr<const OSSymbol>     deviceName;
10842 	OSSharedPtr<OSNumber>           deviceRegId;
10843 	OSSharedPtr<OSNumber>           claimTime;
10844 	OSSharedPtr<OSData>             flagsData;
10845 	OSSharedPtr<OSString>           reasonString;
10846 	OSSharedPtr<OSDictionary>       dict;
10847 	uint64_t                        timestamp;
10848 	bool                            addWakeReason;
10849 
10850 	if (!device || !reason) {
10851 		return;
10852 	}
10853 
10854 	pmEventTimeStamp(&timestamp);
10855 
10856 	IOOptionBits        aotFlags = 0;
10857 	bool                needAOTEvaluate = FALSE;
10858 
10859 	if (kIOPMAOTModeAddEventFlags & _aotMode) {
10860 		if (!strcmp("hold", reason)
10861 		    || !strcmp("help", reason)
10862 		    || !strcmp("menu", reason)
10863 		    || !strcmp("stockholm", reason)
10864 		    || !strcmp("ringer", reason)
10865 		    || !strcmp("ringerab", reason)
10866 		    || !strcmp("smc0", reason)
10867 		    || !strcmp("AOP.RTPWakeupAP", reason)
10868 		    || !strcmp("AOP.RTP_AP_IRQ", reason)
10869 		    || !strcmp("BT.OutboxNotEmpty", reason)
10870 		    || !strcmp("WL.OutboxNotEmpty", reason)) {
10871 			flags |= kIOPMWakeEventAOTExit;
10872 		}
10873 	}
10874 
10875 #if DEVELOPMENT || DEBUG
10876 	if (_aotLingerTime && !strcmp("rtc", reason)) {
10877 		flags |= kIOPMWakeEventAOTPossibleExit;
10878 	}
10879 #endif /* DEVELOPMENT || DEBUG */
10880 
10881 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
10882 	// Publishing the WakeType is serialized by the PM work loop
10883 	if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
10884 		pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10885 		    (void *) _nextScheduledAlarmType.get());
10886 	}
10887 
10888 	// Workaround for the missing wake HID event
10889 	if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
10890 		if (!strcmp("trackpadkeyboard", reason)) {
10891 			pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
10892 			    (void *) gIOPMWakeTypeUserKey.get());
10893 		}
10894 	}
10895 #endif
10896 
10897 	deviceName   = device->copyName(gIOServicePlane);
10898 	deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
10899 	claimTime    = OSNumber::withNumber(timestamp, 64);
10900 	flagsData    = OSData::withValue(flags);
10901 	reasonString = OSString::withCString(reason);
10902 	dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
10903 	if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
10904 		goto done;
10905 	}
10906 
10907 	dict->setObject(gIONameKey, deviceName.get());
10908 	dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
10909 	dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
10910 	dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
10911 	dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
10912 	if (details) {
10913 		dict->setObject(kIOPMWakeEventDetailsKey, details);
10914 	}
10915 
10916 	WAKEEVENT_LOCK();
10917 	addWakeReason = _acceptSystemWakeEvents;
10918 	if (_aotMode) {
10919 		IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
10920 	}
10921 	aotFlags        = (kIOPMWakeEventAOTFlags & flags);
10922 	aotFlags        = (aotFlags & ~_aotPendingFlags);
10923 	needAOTEvaluate = false;
10924 	if (_aotNow && aotFlags) {
10925 		if (kIOPMWakeEventAOTPossibleExit & flags) {
10926 			_aotMetrics->possibleCount++;
10927 		}
10928 		if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
10929 			_aotMetrics->confirmedPossibleCount++;
10930 		}
10931 		if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
10932 			_aotMetrics->rejectedPossibleCount++;
10933 		}
10934 		if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
10935 			_aotMetrics->expiredPossibleCount++;
10936 		}
10937 
10938 		_aotPendingFlags |= aotFlags;
10939 		addWakeReason     = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
10940 		needAOTEvaluate   = _aotReadyToFullWake;
10941 	}
10942 	DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
10943 	    reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
10944 	    _aotNow, pmTracer->getTracePhase(), addWakeReason);
10945 
10946 #if DEVELOPMENT || DEBUG
10947 	if (addWakeReason) {
10948 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
10949 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
10950 		    "Report System Wake Event",
10951 		    "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
10952 		    reason,
10953 		    (int)flags,
10954 		    deviceName->getCStringNoCopy(),
10955 		    device->getRegistryEntryID()
10956 		    );
10957 	}
10958 #endif /* DEVELOPMENT || DEBUG */
10959 
10960 	if (!gWakeReasonSysctlRegistered) {
10961 		// Lazy registration until the platform driver stops registering
10962 		// the same name.
10963 		gWakeReasonSysctlRegistered = true;
10964 	}
10965 	if (addWakeReason) {
10966 		_systemWakeEventsArray->setObject(dict.get());
10967 		if (gWakeReasonString[0] != '\0') {
10968 			strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
10969 		}
10970 		strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
10971 	}
10972 
10973 	WAKEEVENT_UNLOCK();
10974 	if (needAOTEvaluate) {
10975 		// Call aotEvaluate() on PM work loop since it may call
10976 		// aotExit() which accesses PM state.
10977 		pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
10978 	}
10979 
10980 done:
10981 	return;
10982 }
10983 
10984 //******************************************************************************
10985 // claimSystemBootEvent
10986 //
10987 // For a driver to claim a device is the source/conduit of a system boot event.
10988 //******************************************************************************
10989 
10990 void
10991 IOPMrootDomain::claimSystemBootEvent(
10992 	IOService *              device,
10993 	IOOptionBits             flags,
10994 	const char *             reason,
10995 	__unused OSObject *      details )
10996 {
10997 	if (!device || !reason) {
10998 		return;
10999 	}
11000 
11001 	DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11002 #if DEVELOPMENT || DEBUG
11003 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11004 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11005 	    "Report System Boot Device",
11006 	    "Reason: %s Flags: 0x%x Device: %s",
11007 	    reason,
11008 	    (int)flags,
11009 	    device->getName()
11010 	    );
11011 #endif /* DEVELOPMENT || DEBUG */
11012 	WAKEEVENT_LOCK();
11013 	if (!gBootReasonSysctlRegistered) {
11014 		// Lazy sysctl registration after setting gBootReasonString
11015 		strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11016 		os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11017 	}
11018 	WAKEEVENT_UNLOCK();
11019 }
11020 
11021 //******************************************************************************
11022 // claimSystemShutdownEvent
11023 //
11024 // For drivers to claim a system shutdown event on the ensuing boot.
11025 //******************************************************************************
11026 
11027 void
11028 IOPMrootDomain::claimSystemShutdownEvent(
11029 	IOService *              device,
11030 	IOOptionBits             flags,
11031 	const char *             reason,
11032 	__unused OSObject *      details )
11033 {
11034 	if (!device || !reason) {
11035 		return;
11036 	}
11037 
11038 	DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11039 #if DEVELOPMENT || DEBUG
11040 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11041 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11042 	    "Report System Shutdown Cause From Previous Boot",
11043 	    "Reason: %s Flags: 0x%x Device: %s",
11044 	    reason,
11045 	    (int)flags,
11046 	    device->getName()
11047 	    );
11048 #endif /* DEVELOPMENT || DEBUG */
11049 	WAKEEVENT_LOCK();
11050 	if (gShutdownReasonString[0] != '\0') {
11051 		strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11052 	}
11053 	strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11054 
11055 	gShutdownReasonSysctlRegistered = true;
11056 	WAKEEVENT_UNLOCK();
11057 }
11058 
11059 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11060 
11061 // MARK: -
11062 // MARK: PMSettingHandle
11063 
11064 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11065 
11066 void
11067 PMSettingHandle::free( void )
11068 {
11069 	if (pmso) {
11070 		pmso->clientHandleFreed();
11071 		pmso->release();
11072 		pmso = NULL;
11073 	}
11074 
11075 	OSObject::free();
11076 }
11077 
11078 // MARK: -
11079 // MARK: PMSettingObject
11080 
11081 #undef super
11082 #define super OSObject
11083 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11084 
11085 /*
11086  * Static constructor/initializer for PMSettingObject
11087  */
11088 PMSettingObject *PMSettingObject::pmSettingObject(
11089 	IOPMrootDomain                      * parent_arg,
11090 	IOPMSettingControllerCallback       handler_arg,
11091 	OSObject                            * target_arg,
11092 	uintptr_t                           refcon_arg,
11093 	uint32_t                            supportedPowerSources,
11094 	const OSSymbol *                    settings[],
11095 	OSObject                            * *handle_obj)
11096 {
11097 	uint32_t                            settingCount = 0;
11098 	PMSettingObject                     *pmso = NULL;
11099 	PMSettingHandle                     *pmsh = NULL;
11100 
11101 	if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11102 		return NULL;
11103 	}
11104 
11105 	// count OSSymbol entries in NULL terminated settings array
11106 	while (settings[settingCount]) {
11107 		settingCount++;
11108 	}
11109 	if (0 == settingCount) {
11110 		return NULL;
11111 	}
11112 
11113 	pmso = new PMSettingObject;
11114 	if (!pmso || !pmso->init()) {
11115 		goto fail;
11116 	}
11117 
11118 	pmsh = new PMSettingHandle;
11119 	if (!pmsh || !pmsh->init()) {
11120 		goto fail;
11121 	}
11122 
11123 	queue_init(&pmso->calloutQueue);
11124 	pmso->parent       = parent_arg;
11125 	pmso->func         = handler_arg;
11126 	pmso->target       = target_arg;
11127 	pmso->refcon       = refcon_arg;
11128 	pmso->settingCount = settingCount;
11129 
11130 	pmso->retain(); // handle holds a retain on pmso
11131 	pmsh->pmso = pmso;
11132 	pmso->pmsh = pmsh;
11133 
11134 	pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11135 	if (pmso->publishedFeatureID) {
11136 		for (unsigned int i = 0; i < settingCount; i++) {
11137 			// Since there is now at least one listener to this setting, publish
11138 			// PM root domain support for it.
11139 			parent_arg->publishPMSetting( settings[i],
11140 			    supportedPowerSources, &pmso->publishedFeatureID[i] );
11141 		}
11142 	}
11143 
11144 	*handle_obj = pmsh;
11145 	return pmso;
11146 
11147 fail:
11148 	if (pmso) {
11149 		pmso->release();
11150 	}
11151 	if (pmsh) {
11152 		pmsh->release();
11153 	}
11154 	return NULL;
11155 }
11156 
11157 void
11158 PMSettingObject::free( void )
11159 {
11160 	if (publishedFeatureID) {
11161 		for (const auto& featureID : publishedFeatureID) {
11162 			if (featureID) {
11163 				parent->removePublishedFeature( featureID );
11164 			}
11165 		}
11166 
11167 		publishedFeatureID = {};
11168 	}
11169 
11170 	super::free();
11171 }
11172 
11173 IOReturn
11174 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11175 {
11176 	return (*func)(target, type, object, refcon);
11177 }
11178 
11179 void
11180 PMSettingObject::clientHandleFreed( void )
11181 {
11182 	parent->deregisterPMSettingObject(this);
11183 }
11184 
11185 // MARK: -
11186 // MARK: PMAssertionsTracker
11187 
11188 //*********************************************************************************
11189 //*********************************************************************************
11190 //*********************************************************************************
11191 // class PMAssertionsTracker Implementation
11192 
11193 #define kAssertUniqueIDStart    500
11194 
11195 PMAssertionsTracker *
11196 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11197 {
11198 	PMAssertionsTracker    *me;
11199 
11200 	me = new PMAssertionsTracker;
11201 	if (!me || !me->init()) {
11202 		if (me) {
11203 			me->release();
11204 		}
11205 		return NULL;
11206 	}
11207 
11208 	me->owner = rootDomain;
11209 	me->issuingUniqueID = kAssertUniqueIDStart;
11210 	me->assertionsArray = OSArray::withCapacity(5);
11211 	me->assertionsKernel = 0;
11212 	me->assertionsUser = 0;
11213 	me->assertionsCombined = 0;
11214 	me->assertionsArrayLock = IOLockAlloc();
11215 	me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11216 
11217 	assert(me->assertionsArray);
11218 	assert(me->assertionsArrayLock);
11219 
11220 	return me;
11221 }
11222 
11223 /* tabulate
11224  * - Update assertionsKernel to reflect the state of all
11225  * assertions in the kernel.
11226  * - Update assertionsCombined to reflect both kernel & user space.
11227  */
11228 void
11229 PMAssertionsTracker::tabulate(void)
11230 {
11231 	int i;
11232 	int count;
11233 	const PMAssertStruct *_a = nullptr;
11234 	OSValueObject<PMAssertStruct> *_d = nullptr;
11235 
11236 	IOPMDriverAssertionType oldKernel = assertionsKernel;
11237 	IOPMDriverAssertionType oldCombined = assertionsCombined;
11238 
11239 	ASSERT_GATED();
11240 
11241 	assertionsKernel = 0;
11242 	assertionsCombined = 0;
11243 
11244 	if (!assertionsArray) {
11245 		return;
11246 	}
11247 
11248 	if ((count = assertionsArray->getCount())) {
11249 		for (i = 0; i < count; i++) {
11250 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11251 			if (_d) {
11252 				_a = _d->getBytesNoCopy();
11253 				if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11254 					assertionsKernel |= _a->assertionBits;
11255 				}
11256 			}
11257 		}
11258 	}
11259 
11260 	tabulateProducerCount++;
11261 	assertionsCombined = assertionsKernel | assertionsUser;
11262 
11263 	if ((assertionsKernel != oldKernel) ||
11264 	    (assertionsCombined != oldCombined)) {
11265 		owner->evaluateAssertions(assertionsCombined, oldCombined);
11266 	}
11267 }
11268 
11269 void
11270 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11271 {
11272 	AbsoluteTime now;
11273 	uint64_t     nsec;
11274 
11275 	if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11276 	    (assertStruct->assertCPUStartTime == 0)) {
11277 		return;
11278 	}
11279 
11280 	now = mach_absolute_time();
11281 	SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11282 	absolutetime_to_nanoseconds(now, &nsec);
11283 	assertStruct->assertCPUDuration += nsec;
11284 	assertStruct->assertCPUStartTime = 0;
11285 
11286 	if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11287 		maxAssertCPUDuration = assertStruct->assertCPUDuration;
11288 		maxAssertCPUEntryId = assertStruct->registryEntryID;
11289 	}
11290 }
11291 
11292 void
11293 PMAssertionsTracker::reportCPUBitAccounting( void )
11294 {
11295 	const PMAssertStruct *_a = nullptr;
11296 	OSValueObject<PMAssertStruct> *_d = nullptr;
11297 	int            i, count;
11298 	AbsoluteTime   now;
11299 	uint64_t       nsec;
11300 
11301 	ASSERT_GATED();
11302 
11303 	// Account for drivers that are still holding the CPU assertion
11304 	if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11305 		now = mach_absolute_time();
11306 		if ((count = assertionsArray->getCount())) {
11307 			for (i = 0; i < count; i++) {
11308 				_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11309 				if (_d) {
11310 					_a = _d->getBytesNoCopy();
11311 					if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11312 					    (_a->level == kIOPMDriverAssertionLevelOn) &&
11313 					    (_a->assertCPUStartTime != 0)) {
11314 						// Don't modify PMAssertStruct, leave that
11315 						// for updateCPUBitAccounting()
11316 						SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11317 						absolutetime_to_nanoseconds(now, &nsec);
11318 						nsec += _a->assertCPUDuration;
11319 						if (nsec > maxAssertCPUDuration) {
11320 							maxAssertCPUDuration = nsec;
11321 							maxAssertCPUEntryId = _a->registryEntryID;
11322 						}
11323 					}
11324 				}
11325 			}
11326 		}
11327 	}
11328 
11329 	if (maxAssertCPUDuration) {
11330 		DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11331 		    (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11332 	}
11333 
11334 	maxAssertCPUDuration = 0;
11335 	maxAssertCPUEntryId = 0;
11336 }
11337 
11338 void
11339 PMAssertionsTracker::publishProperties( void )
11340 {
11341 	OSSharedPtr<OSArray>             assertionsSummary;
11342 
11343 	if (tabulateConsumerCount != tabulateProducerCount) {
11344 		IOLockLock(assertionsArrayLock);
11345 
11346 		tabulateConsumerCount = tabulateProducerCount;
11347 
11348 		/* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11349 		 */
11350 		assertionsSummary = copyAssertionsArray();
11351 		if (assertionsSummary) {
11352 			owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11353 		} else {
11354 			owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11355 		}
11356 
11357 		/* Publish the IOPMrootDomain property "DriverPMAssertions"
11358 		 */
11359 		owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11360 
11361 		IOLockUnlock(assertionsArrayLock);
11362 	}
11363 }
11364 
11365 PMAssertStruct *
11366 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11367 {
11368 	PMAssertStruct      *_a = NULL;
11369 	OSValueObject<PMAssertStruct> *_d = nullptr;
11370 	int                 found = -1;
11371 	int                 count = 0;
11372 	int                 i = 0;
11373 
11374 	if (assertionsArray
11375 	    && (count = assertionsArray->getCount())) {
11376 		for (i = 0; i < count; i++) {
11377 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11378 			if (_d) {
11379 				_a = _d->getMutableBytesNoCopy();
11380 				if (_a && (_id == _a->id)) {
11381 					found = i;
11382 					break;
11383 				}
11384 			}
11385 		}
11386 	}
11387 
11388 	if (-1 == found) {
11389 		return NULL;
11390 	} else {
11391 		if (index) {
11392 			*index = found;
11393 		}
11394 		return _a;
11395 	}
11396 }
11397 
11398 /* PMAssertionsTracker::handleCreateAssertion
11399  * Perform assertion work on the PM workloop. Do not call directly.
11400  */
11401 IOReturn
11402 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11403 {
11404 	PMAssertStruct *assertStruct = nullptr;
11405 
11406 	ASSERT_GATED();
11407 
11408 	if (newAssertion) {
11409 		IOLockLock(assertionsArrayLock);
11410 		assertStruct = newAssertion->getMutableBytesNoCopy();
11411 		if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11412 		    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11413 			assertStruct->assertCPUStartTime = mach_absolute_time();
11414 		}
11415 		assertionsArray->setObject(newAssertion);
11416 		IOLockUnlock(assertionsArrayLock);
11417 		newAssertion->release();
11418 
11419 		tabulate();
11420 	}
11421 	return kIOReturnSuccess;
11422 }
11423 
11424 /* PMAssertionsTracker::createAssertion
11425  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11426  * appropiate.
11427  */
11428 IOReturn
11429 PMAssertionsTracker::createAssertion(
11430 	IOPMDriverAssertionType which,
11431 	IOPMDriverAssertionLevel level,
11432 	IOService *serviceID,
11433 	const char *whoItIs,
11434 	IOPMDriverAssertionID *outID)
11435 {
11436 	OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11437 	PMAssertStruct  track;
11438 
11439 	// Warning: trillions and trillions of created assertions may overflow the unique ID.
11440 	track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11441 	track.level = level;
11442 	track.assertionBits = which;
11443 
11444 	// NB: ownerString is explicitly managed by PMAssertStruct
11445 	// it will be released in `handleReleaseAssertion' below
11446 	track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11447 	track.ownerService = serviceID;
11448 	track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11449 	track.modifiedTime = 0;
11450 	pmEventTimeStamp(&track.createdTime);
11451 	track.assertCPUStartTime = 0;
11452 	track.assertCPUDuration = 0;
11453 
11454 	dataStore = OSValueObjectWithValue(track);
11455 	if (!dataStore) {
11456 		if (track.ownerString) {
11457 			track.ownerString->release();
11458 			track.ownerString = NULL;
11459 		}
11460 		return kIOReturnNoMemory;
11461 	}
11462 
11463 	*outID = track.id;
11464 
11465 	if (owner && owner->pmPowerStateQueue) {
11466 		// queue action is responsible for releasing dataStore
11467 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11468 	}
11469 
11470 	return kIOReturnSuccess;
11471 }
11472 
11473 /* PMAssertionsTracker::handleReleaseAssertion
11474  * Runs in PM workloop. Do not call directly.
11475  */
11476 IOReturn
11477 PMAssertionsTracker::handleReleaseAssertion(
11478 	IOPMDriverAssertionID _id)
11479 {
11480 	ASSERT_GATED();
11481 
11482 	int             index;
11483 	PMAssertStruct  *assertStruct = detailsForID(_id, &index);
11484 
11485 	if (!assertStruct) {
11486 		return kIOReturnNotFound;
11487 	}
11488 
11489 	IOLockLock(assertionsArrayLock);
11490 
11491 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11492 	    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11493 		updateCPUBitAccounting(assertStruct);
11494 	}
11495 
11496 	if (assertStruct->ownerString) {
11497 		assertStruct->ownerString->release();
11498 		assertStruct->ownerString = NULL;
11499 	}
11500 
11501 	assertionsArray->removeObject(index);
11502 	IOLockUnlock(assertionsArrayLock);
11503 
11504 	tabulate();
11505 	return kIOReturnSuccess;
11506 }
11507 
11508 /* PMAssertionsTracker::releaseAssertion
11509  * Releases an assertion and affects system behavior if appropiate.
11510  * Actual work happens on PM workloop.
11511  */
11512 IOReturn
11513 PMAssertionsTracker::releaseAssertion(
11514 	IOPMDriverAssertionID _id)
11515 {
11516 	if (owner && owner->pmPowerStateQueue) {
11517 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11518 	}
11519 	return kIOReturnSuccess;
11520 }
11521 
11522 /* PMAssertionsTracker::handleSetAssertionLevel
11523  * Runs in PM workloop. Do not call directly.
11524  */
11525 IOReturn
11526 PMAssertionsTracker::handleSetAssertionLevel(
11527 	IOPMDriverAssertionID    _id,
11528 	IOPMDriverAssertionLevel _level)
11529 {
11530 	PMAssertStruct      *assertStruct = detailsForID(_id, NULL);
11531 
11532 	ASSERT_GATED();
11533 
11534 	if (!assertStruct) {
11535 		return kIOReturnNotFound;
11536 	}
11537 
11538 	IOLockLock(assertionsArrayLock);
11539 	pmEventTimeStamp(&assertStruct->modifiedTime);
11540 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11541 	    (assertStruct->level != _level)) {
11542 		if (_level == kIOPMDriverAssertionLevelOn) {
11543 			assertStruct->assertCPUStartTime = mach_absolute_time();
11544 		} else {
11545 			updateCPUBitAccounting(assertStruct);
11546 		}
11547 	}
11548 	assertStruct->level = _level;
11549 	IOLockUnlock(assertionsArrayLock);
11550 
11551 	tabulate();
11552 	return kIOReturnSuccess;
11553 }
11554 
11555 /* PMAssertionsTracker::setAssertionLevel
11556  */
11557 IOReturn
11558 PMAssertionsTracker::setAssertionLevel(
11559 	IOPMDriverAssertionID    _id,
11560 	IOPMDriverAssertionLevel _level)
11561 {
11562 	if (owner && owner->pmPowerStateQueue) {
11563 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
11564 		    (void *)(uintptr_t)_level, _id);
11565 	}
11566 
11567 	return kIOReturnSuccess;
11568 }
11569 
11570 IOReturn
11571 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
11572 {
11573 	IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
11574 
11575 	ASSERT_GATED();
11576 
11577 	if (new_user_levels != assertionsUser) {
11578 		DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
11579 		assertionsUser = new_user_levels;
11580 	}
11581 
11582 	tabulate();
11583 	return kIOReturnSuccess;
11584 }
11585 
11586 IOReturn
11587 PMAssertionsTracker::setUserAssertionLevels(
11588 	IOPMDriverAssertionType new_user_levels)
11589 {
11590 	if (gIOPMWorkLoop) {
11591 		gIOPMWorkLoop->runAction(
11592 			OSMemberFunctionCast(
11593 				IOWorkLoop::Action,
11594 				this,
11595 				&PMAssertionsTracker::handleSetUserAssertionLevels),
11596 			this,
11597 			(void *) &new_user_levels, NULL, NULL, NULL);
11598 	}
11599 
11600 	return kIOReturnSuccess;
11601 }
11602 
11603 
11604 OSSharedPtr<OSArray>
11605 PMAssertionsTracker::copyAssertionsArray(void)
11606 {
11607 	int count;
11608 	int i;
11609 	OSSharedPtr<OSArray>     outArray = NULL;
11610 
11611 	if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
11612 		goto exit;
11613 	}
11614 	outArray = OSArray::withCapacity(count);
11615 	if (!outArray) {
11616 		goto exit;
11617 	}
11618 
11619 	for (i = 0; i < count; i++) {
11620 		const PMAssertStruct *_a = nullptr;
11621 		OSValueObject<PMAssertStruct> *_d = nullptr;
11622 		OSSharedPtr<OSDictionary>    details;
11623 
11624 		_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11625 		if (_d && (_a = _d->getBytesNoCopy())) {
11626 			OSSharedPtr<OSNumber>        _n;
11627 
11628 			details = OSDictionary::withCapacity(7);
11629 			if (!details) {
11630 				continue;
11631 			}
11632 
11633 			outArray->setObject(details.get());
11634 
11635 			_n = OSNumber::withNumber(_a->id, 64);
11636 			if (_n) {
11637 				details->setObject(kIOPMDriverAssertionIDKey, _n.get());
11638 			}
11639 			_n = OSNumber::withNumber(_a->createdTime, 64);
11640 			if (_n) {
11641 				details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
11642 			}
11643 			_n = OSNumber::withNumber(_a->modifiedTime, 64);
11644 			if (_n) {
11645 				details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
11646 			}
11647 			_n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
11648 			if (_n) {
11649 				details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
11650 			}
11651 			_n = OSNumber::withNumber(_a->level, 64);
11652 			if (_n) {
11653 				details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
11654 			}
11655 			_n = OSNumber::withNumber(_a->assertionBits, 64);
11656 			if (_n) {
11657 				details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
11658 			}
11659 
11660 			if (_a->ownerString) {
11661 				details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
11662 			}
11663 		}
11664 	}
11665 
11666 exit:
11667 	return os::move(outArray);
11668 }
11669 
11670 IOPMDriverAssertionType
11671 PMAssertionsTracker::getActivatedAssertions(void)
11672 {
11673 	return assertionsCombined;
11674 }
11675 
11676 IOPMDriverAssertionLevel
11677 PMAssertionsTracker::getAssertionLevel(
11678 	IOPMDriverAssertionType type)
11679 {
11680 	// FIXME: unused and also wrong
11681 	if (type && ((type & assertionsKernel) == assertionsKernel)) {
11682 		return kIOPMDriverAssertionLevelOn;
11683 	} else {
11684 		return kIOPMDriverAssertionLevelOff;
11685 	}
11686 }
11687 
11688 //*********************************************************************************
11689 //*********************************************************************************
11690 //*********************************************************************************
11691 
11692 
11693 static void
11694 pmEventTimeStamp(uint64_t *recordTS)
11695 {
11696 	clock_sec_t     tsec;
11697 	clock_usec_t    tusec;
11698 
11699 	if (!recordTS) {
11700 		return;
11701 	}
11702 
11703 	// We assume tsec fits into 32 bits; 32 bits holds enough
11704 	// seconds for 136 years since the epoch in 1970.
11705 	clock_get_calendar_microtime(&tsec, &tusec);
11706 
11707 
11708 	// Pack the sec & microsec calendar time into a uint64_t, for fun.
11709 	*recordTS = 0;
11710 	*recordTS |= (uint32_t)tusec;
11711 	*recordTS |= ((uint64_t)tsec << 32);
11712 
11713 	return;
11714 }
11715 
11716 // MARK: -
11717 // MARK: IORootParent
11718 
11719 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11720 
11721 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
11722 
11723 // The reason that root domain needs a root parent is to facilitate demand
11724 // sleep, since a power change from the root parent cannot be vetoed.
11725 //
11726 // The above statement is no longer true since root domain now performs
11727 // demand sleep using overrides. But root parent remains to avoid changing
11728 // the power tree stacking. Root parent is parked at the max power state.
11729 
11730 
11731 static IOPMPowerState patriarchPowerStates[2] =
11732 {
11733 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11734 	{1, 0, ON_POWER, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11735 };
11736 
11737 void
11738 IORootParent::initialize( void )
11739 {
11740 
11741 	gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
11742 	gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
11743 	gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
11744 	gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
11745 	gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
11746 	gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
11747 	gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
11748 	gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
11749 	gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
11750 	gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
11751 	gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
11752 	gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
11753 	gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
11754 	gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
11755 	gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
11756 	gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
11757 	gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
11758 	gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
11759 	gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
11760 	gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
11761 	gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
11762 	gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
11763 	gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
11764 	gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
11765 	gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
11766 	gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
11767 	gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
11768 	gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
11769 	gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
11770 	gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
11771 	gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
11772 	gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
11773 	gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
11774 	gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
11775 	gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
11776 	gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
11777 	gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
11778 	gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
11779 	gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
11780 	gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
11781 	gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
11782 	gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
11783 	gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
11784 	gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
11785 }
11786 
11787 bool
11788 IORootParent::start( IOService * nub )
11789 {
11790 	IOService::start(nub);
11791 	attachToParent( getRegistryRoot(), gIOPowerPlane );
11792 	PMinit();
11793 	registerPowerDriver(this, patriarchPowerStates, 2);
11794 	makeUsable();
11795 	return true;
11796 }
11797 
11798 void
11799 IORootParent::shutDownSystem( void )
11800 {
11801 }
11802 
11803 void
11804 IORootParent::restartSystem( void )
11805 {
11806 }
11807 
11808 void
11809 IORootParent::sleepSystem( void )
11810 {
11811 }
11812 
11813 void
11814 IORootParent::dozeSystem( void )
11815 {
11816 }
11817 
11818 void
11819 IORootParent::sleepToDoze( void )
11820 {
11821 }
11822 
11823 void
11824 IORootParent::wakeSystem( void )
11825 {
11826 }
11827 
11828 OSSharedPtr<OSObject>
11829 IORootParent::copyProperty( const char * aKey) const
11830 {
11831 	return IOService::copyProperty(aKey);
11832 }
11833 
11834 uint32_t
11835 IOPMrootDomain::getWatchdogTimeout()
11836 {
11837 	if (gSwdSleepWakeTimeout) {
11838 		gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
11839 	}
11840 	if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
11841 	    (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
11842 		return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
11843 	} else {
11844 		return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
11845 	}
11846 }
11847 
11848 
11849 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
11850 IOReturn
11851 IOPMrootDomain::restartWithStackshot()
11852 {
11853 	takeStackshot(true);
11854 
11855 	return kIOReturnSuccess;
11856 }
11857 
11858 void
11859 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
11860 {
11861 	takeStackshot(wdogTrigger);
11862 }
11863 
11864 void
11865 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
11866 {
11867 	switch (tracePhase) {
11868 	case kIOPMTracePointSleepStarted:
11869 		*phaseString = "kIOPMTracePointSleepStarted";
11870 		*description = "starting sleep";
11871 		break;
11872 
11873 	case kIOPMTracePointSleepApplications:
11874 		*phaseString = "kIOPMTracePointSleepApplications";
11875 		*description = "notifying applications";
11876 		break;
11877 
11878 	case kIOPMTracePointSleepPriorityClients:
11879 		*phaseString = "kIOPMTracePointSleepPriorityClients";
11880 		*description = "notifying clients about upcoming system capability changes";
11881 		break;
11882 
11883 	case kIOPMTracePointSleepWillChangeInterests:
11884 		*phaseString = "kIOPMTracePointSleepWillChangeInterests";
11885 		*description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
11886 		break;
11887 
11888 	case kIOPMTracePointSleepPowerPlaneDrivers:
11889 		*phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
11890 		*description = "calling power state change callbacks";
11891 		break;
11892 
11893 	case kIOPMTracePointSleepDidChangeInterests:
11894 		*phaseString = "kIOPMTracePointSleepDidChangeInterests";
11895 		*description = "calling rootDomain's clients about rootDomain's state changes";
11896 		break;
11897 
11898 	case kIOPMTracePointSleepCapabilityClients:
11899 		*phaseString = "kIOPMTracePointSleepCapabilityClients";
11900 		*description = "notifying clients about current system capabilities";
11901 		break;
11902 
11903 	case kIOPMTracePointSleepPlatformActions:
11904 		*phaseString = "kIOPMTracePointSleepPlatformActions";
11905 		*description = "calling Quiesce/Sleep action callbacks";
11906 		break;
11907 
11908 	case kIOPMTracePointSleepCPUs:
11909 	{
11910 		*phaseString = "kIOPMTracePointSleepCPUs";
11911 #if defined(__i386__) || defined(__x86_64__)
11912 		/*
11913 		 * We cannot use the getCPUNumber() method to get the cpu number, since
11914 		 * that cpu number is unrelated to the cpu number we need (we need the cpu
11915 		 * number as enumerated by the scheduler, NOT the CPU number enumerated
11916 		 * by ACPIPlatform as the CPUs are enumerated in MADT order).
11917 		 * Instead, pass the Mach processor pointer associated with the current
11918 		 * shutdown target so its associated cpu_id can be used in
11919 		 * processor_to_datastring.
11920 		 */
11921 		if (currentShutdownTarget != NULL &&
11922 		    currentShutdownTarget->getMachProcessor() != NULL) {
11923 			const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
11924 			    currentShutdownTarget->getMachProcessor());
11925 			*description = sbuf;
11926 		} else {
11927 			*description = "halting all non-boot CPUs";
11928 		}
11929 #else
11930 		*description = "halting all non-boot CPUs";
11931 #endif
11932 		break;
11933 	}
11934 	case kIOPMTracePointSleepPlatformDriver:
11935 		*phaseString = "kIOPMTracePointSleepPlatformDriver";
11936 		*description = "executing platform specific code";
11937 		break;
11938 
11939 	case kIOPMTracePointHibernate:
11940 		*phaseString = "kIOPMTracePointHibernate";
11941 		*description = "writing the hibernation image";
11942 		break;
11943 
11944 	case kIOPMTracePointSystemSleep:
11945 		*phaseString = "kIOPMTracePointSystemSleep";
11946 		*description = "in EFI/Bootrom after last point of entry to sleep";
11947 		break;
11948 
11949 	case kIOPMTracePointWakePlatformDriver:
11950 		*phaseString = "kIOPMTracePointWakePlatformDriver";
11951 		*description = "executing platform specific code";
11952 		break;
11953 
11954 
11955 	case kIOPMTracePointWakePlatformActions:
11956 		*phaseString = "kIOPMTracePointWakePlatformActions";
11957 		*description = "calling Wake action callbacks";
11958 		break;
11959 
11960 	case kIOPMTracePointWakeCPUs:
11961 		*phaseString = "kIOPMTracePointWakeCPUs";
11962 		*description = "starting non-boot CPUs";
11963 		break;
11964 
11965 	case kIOPMTracePointWakeWillPowerOnClients:
11966 		*phaseString = "kIOPMTracePointWakeWillPowerOnClients";
11967 		*description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
11968 		break;
11969 
11970 	case kIOPMTracePointWakeWillChangeInterests:
11971 		*phaseString = "kIOPMTracePointWakeWillChangeInterests";
11972 		*description = "calling rootDomain's clients about upcoming rootDomain's state changes";
11973 		break;
11974 
11975 	case kIOPMTracePointWakeDidChangeInterests:
11976 		*phaseString = "kIOPMTracePointWakeDidChangeInterests";
11977 		*description = "calling rootDomain's clients about completed rootDomain's state changes";
11978 		break;
11979 
11980 	case kIOPMTracePointWakePowerPlaneDrivers:
11981 		*phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
11982 		*description = "calling power state change callbacks";
11983 		break;
11984 
11985 	case kIOPMTracePointWakeCapabilityClients:
11986 		*phaseString = "kIOPMTracePointWakeCapabilityClients";
11987 		*description = "informing clients about current system capabilities";
11988 		break;
11989 
11990 	case kIOPMTracePointWakeApplications:
11991 		*phaseString = "kIOPMTracePointWakeApplications";
11992 		*description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
11993 		break;
11994 
11995 	case kIOPMTracePointDarkWakeEntry:
11996 		*phaseString = "kIOPMTracePointDarkWakeEntry";
11997 		*description = "entering darkwake on way to sleep";
11998 		break;
11999 
12000 	case kIOPMTracePointDarkWakeExit:
12001 		*phaseString = "kIOPMTracePointDarkWakeExit";
12002 		*description = "entering fullwake from darkwake";
12003 		break;
12004 
12005 	default:
12006 		*phaseString = NULL;
12007 		*description = NULL;
12008 	}
12009 }
12010 
12011 void
12012 IOPMrootDomain::saveFailureData2File()
12013 {
12014 	unsigned int len = 0;
12015 	char  failureStr[512];
12016 	errno_t error;
12017 	char *outbuf;
12018 	OSNumber *statusCode;
12019 	uint64_t pmStatusCode = 0;
12020 	uint32_t phaseData = 0;
12021 	uint32_t phaseDetail = 0;
12022 	bool efiFailure = false;
12023 
12024 	OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12025 	statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12026 	if (statusCode) {
12027 		pmStatusCode = statusCode->unsigned64BitValue();
12028 		phaseData = pmStatusCode & 0xFFFFFFFF;
12029 		phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12030 		if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12031 			LOG("Sleep Wake failure in EFI\n");
12032 			efiFailure = true;
12033 			failureStr[0] = 0;
12034 			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);
12035 			len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12036 		}
12037 	}
12038 
12039 	if (!efiFailure) {
12040 		if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12041 			swd_flags |= SWD_BOOT_BY_SW_WDOG;
12042 			PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12043 			// dump panic will handle saving nvram data
12044 			return;
12045 		}
12046 
12047 		/* Keeping this around for capturing data during power
12048 		 * button press */
12049 
12050 		if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12051 			DLOG("No sleep wake failure string\n");
12052 			return;
12053 		}
12054 		if (len == 0) {
12055 			DLOG("Ignoring zero byte SleepWake failure string\n");
12056 			goto exit;
12057 		}
12058 
12059 		// if PMStatus code is zero, delete stackshot and return
12060 		if (statusCode) {
12061 			if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12062 				// there was no sleep wake failure
12063 				// this can happen if delete stackshot was called
12064 				// before take stackshot completed. Let us delete any
12065 				// sleep wake failure data in nvram
12066 				DLOG("Deleting stackshot on successful wake\n");
12067 				deleteStackshot();
12068 				return;
12069 			}
12070 		}
12071 
12072 		if (len > sizeof(failureStr)) {
12073 			len = sizeof(failureStr);
12074 		}
12075 		failureStr[0] = 0;
12076 		PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12077 	}
12078 	if (failureStr[0] != 0) {
12079 		error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12080 		if (error) {
12081 			DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12082 		} else {
12083 			DLOG("Saved SleepWake failure string to file.\n");
12084 		}
12085 	}
12086 
12087 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12088 		goto exit;
12089 	}
12090 
12091 	if (swd_buffer) {
12092 		unsigned int len = 0;
12093 		errno_t error;
12094 		char nvram_var_name_buffer[20];
12095 		unsigned int concat_len = 0;
12096 		swd_hdr      *hdr = NULL;
12097 
12098 
12099 		hdr = (swd_hdr *)swd_buffer;
12100 		outbuf = (char *)hdr + hdr->spindump_offset;
12101 		OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12102 
12103 		for (int i = 0; i < 8; i++) {
12104 			snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12105 			if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12106 				LOG("No SleepWake blob to read beyond chunk %d\n", i);
12107 				break;
12108 			}
12109 			if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12110 				PERemoveNVRAMProperty(nvram_var_name_buffer);
12111 				LOG("Could not read the property :-(\n");
12112 				break;
12113 			}
12114 			PERemoveNVRAMProperty(nvram_var_name_buffer);
12115 			concat_len += len;
12116 		}
12117 		LOG("Concatenated length for the SWD blob %d\n", concat_len);
12118 
12119 		if (concat_len) {
12120 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12121 			if (error) {
12122 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12123 			} else {
12124 				LOG("Saved SleepWake zipped data to file.\n");
12125 			}
12126 		} else {
12127 			// There is a sleep wake failure string but no stackshot
12128 			// Write a placeholder stacks file so that swd runs
12129 			snprintf(outbuf, 20, "%s", "No stackshot data\n");
12130 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12131 			if (error) {
12132 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12133 			} else {
12134 				LOG("Saved SleepWake zipped data to file.\n");
12135 			}
12136 		}
12137 	} else {
12138 		LOG("No buffer allocated to save failure stackshot\n");
12139 	}
12140 
12141 
12142 	gRootDomain->swd_lock = 0;
12143 exit:
12144 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12145 	return;
12146 }
12147 
12148 
12149 void
12150 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12151 {
12152 	OSSharedPtr<IORegistryIterator>    iter;
12153 	OSSharedPtr<const OSSymbol>        kextName = NULL;
12154 	IORegistryEntry *       entry;
12155 	IOService *             node;
12156 	bool                    nodeFound = false;
12157 
12158 	const void *            callMethod = NULL;
12159 	const char *            objectName = NULL;
12160 	uint32_t                timeout = getWatchdogTimeout();
12161 	const char *            phaseString = NULL;
12162 	const char *            phaseDescription = NULL;
12163 
12164 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12165 	uint32_t tracePhase = pmTracer->getTracePhase();
12166 
12167 	*thread = NULL;
12168 	if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12169 		snprintf(failureStr, strLen, "Sleep transition timed out after %d seconds", timeout);
12170 	} else {
12171 		snprintf(failureStr, strLen, "Wake transition timed out after %d seconds", timeout);
12172 	}
12173 	tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12174 
12175 	if (notifierThread) {
12176 		if (notifier && (notifier->identifier)) {
12177 			objectName = notifier->identifier->getCStringNoCopy();
12178 		}
12179 		*thread = notifierThread;
12180 	} else {
12181 		iter = IORegistryIterator::iterateOver(
12182 			getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12183 
12184 		if (iter) {
12185 			while ((entry = iter->getNextObject())) {
12186 				node = OSDynamicCast(IOService, entry);
12187 				if (!node) {
12188 					continue;
12189 				}
12190 				if (OSDynamicCast(IOPowerConnection, node)) {
12191 					continue;
12192 				}
12193 
12194 				if (node->getBlockingDriverCall(thread, &callMethod)) {
12195 					nodeFound = true;
12196 					break;
12197 				}
12198 			}
12199 		}
12200 		if (nodeFound) {
12201 			kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12202 			if (kextName) {
12203 				objectName = kextName->getCStringNoCopy();
12204 			}
12205 		}
12206 	}
12207 	if (phaseDescription) {
12208 		strlcat(failureStr, " while ", strLen);
12209 		strlcat(failureStr, phaseDescription, strLen);
12210 		strlcat(failureStr, ".", strLen);
12211 	}
12212 	if (objectName) {
12213 		strlcat(failureStr, " Suspected bundle: ", strLen);
12214 		strlcat(failureStr, objectName, strLen);
12215 		strlcat(failureStr, ".", strLen);
12216 	}
12217 	if (*thread) {
12218 		char threadName[40];
12219 		snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12220 		strlcat(failureStr, threadName, strLen);
12221 	}
12222 
12223 	DLOG("%s\n", failureStr);
12224 }
12225 
12226 struct swd_stackshot_compressed_data {
12227 	z_output_func   zoutput;
12228 	size_t                  zipped;
12229 	uint64_t                totalbytes;
12230 	uint64_t                lastpercent;
12231 	IOReturn                error;
12232 	unsigned                outremain;
12233 	unsigned                outlen;
12234 	unsigned                writes;
12235 	Bytef *                 outbuf;
12236 };
12237 struct swd_stackshot_compressed_data swd_zip_var = { };
12238 
12239 static void *
12240 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12241 {
12242 	void *result;
12243 	LOG("Alloc in zipping %d items of size %d\n", items, size);
12244 
12245 	result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12246 	swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12247 	LOG("Offset %zu\n", swd_zs_zoffset);
12248 	return result;
12249 }
12250 
12251 static int
12252 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12253 {
12254 	unsigned len;
12255 
12256 	len = strm->avail_in;
12257 
12258 	if (len > size) {
12259 		len = size;
12260 	}
12261 	if (len == 0) {
12262 		return 0;
12263 	}
12264 
12265 	if (strm->next_in != (Bytef *) strm) {
12266 		memcpy(buf, strm->next_in, len);
12267 	} else {
12268 		bzero(buf, len);
12269 	}
12270 
12271 	strm->adler = z_crc32(strm->adler, buf, len);
12272 
12273 	strm->avail_in -= len;
12274 	strm->next_in  += len;
12275 	strm->total_in += len;
12276 
12277 	return (int)len;
12278 }
12279 
12280 static int
12281 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12282 {
12283 	unsigned int i = 0;
12284 	// if outlen > max size don't add to the buffer
12285 	assert(buf != NULL);
12286 	if (strm && buf) {
12287 		if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12288 			LOG("No space to GZIP... not writing to NVRAM\n");
12289 			return len;
12290 		}
12291 	}
12292 	for (i = 0; i < len; i++) {
12293 		*(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12294 	}
12295 	swd_zip_var.outlen += len;
12296 	return len;
12297 }
12298 
12299 static void
12300 swd_zs_free(void * __unused ref, void * __unused ptr)
12301 {
12302 }
12303 
12304 static int
12305 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12306 {
12307 	int wbits = 12;
12308 	int memlevel = 3;
12309 
12310 	if (((unsigned int) numBytes) != numBytes) {
12311 		return 0;
12312 	}
12313 
12314 	if (!swd_zs.zalloc) {
12315 		swd_zs.zalloc = swd_zs_alloc;
12316 		swd_zs.zfree = swd_zs_free;
12317 		if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12318 			// allocation failed
12319 			bzero(&swd_zs, sizeof(swd_zs));
12320 			// swd_zs_zoffset = 0;
12321 		} else {
12322 			LOG("PMRD inited the zlib allocation routines\n");
12323 		}
12324 	}
12325 
12326 	swd_zip_var.zipped = 0;
12327 	swd_zip_var.totalbytes = 0; // should this be the max that we have?
12328 	swd_zip_var.lastpercent = 0;
12329 	swd_zip_var.error = kIOReturnSuccess;
12330 	swd_zip_var.outremain = 0;
12331 	swd_zip_var.outlen = 0;
12332 	swd_zip_var.writes = 0;
12333 	swd_zip_var.outbuf = (Bytef *)outPtr;
12334 
12335 	swd_zip_var.totalbytes = numBytes;
12336 
12337 	swd_zs.avail_in = 0;
12338 	swd_zs.next_in = NULL;
12339 	swd_zs.avail_out = 0;
12340 	swd_zs.next_out = NULL;
12341 
12342 	deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12343 
12344 	z_stream *zs;
12345 	int zr;
12346 	zs = &swd_zs;
12347 
12348 	while (swd_zip_var.error >= 0) {
12349 		if (!zs->avail_in) {
12350 			zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12351 			zs->avail_in = (unsigned int) numBytes;
12352 		}
12353 		if (!zs->avail_out) {
12354 			zs->next_out = (Bytef *)zs;
12355 			zs->avail_out = UINT32_MAX;
12356 		}
12357 		zr = deflate(zs, Z_NO_FLUSH);
12358 		if (Z_STREAM_END == zr) {
12359 			break;
12360 		}
12361 		if (zr != Z_OK) {
12362 			LOG("ZERR %d\n", zr);
12363 			swd_zip_var.error = zr;
12364 		} else {
12365 			if (zs->total_in == numBytes) {
12366 				break;
12367 			}
12368 		}
12369 	}
12370 
12371 	//now flush the stream
12372 	while (swd_zip_var.error >= 0) {
12373 		if (!zs->avail_out) {
12374 			zs->next_out = (Bytef *)zs;
12375 			zs->avail_out = UINT32_MAX;
12376 		}
12377 		zr = deflate(zs, Z_FINISH);
12378 		if (Z_STREAM_END == zr) {
12379 			break;
12380 		}
12381 		if (zr != Z_OK) {
12382 			LOG("ZERR %d\n", zr);
12383 			swd_zip_var.error = zr;
12384 		} else {
12385 			if (zs->total_in == numBytes) {
12386 				LOG("Total output size %d\n", swd_zip_var.outlen);
12387 				break;
12388 			}
12389 		}
12390 	}
12391 
12392 	return swd_zip_var.outlen;
12393 }
12394 
12395 void
12396 IOPMrootDomain::deleteStackshot()
12397 {
12398 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12399 		// takeStackshot hasn't completed
12400 		return;
12401 	}
12402 	LOG("Deleting any sleepwake failure data in nvram\n");
12403 
12404 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12405 	char nvram_var_name_buf[20];
12406 	for (int i = 0; i < 8; i++) {
12407 		snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12408 		if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12409 			LOG("Removing %s returned false\n", nvram_var_name_buf);
12410 		}
12411 	}
12412 	// force NVRAM sync
12413 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12414 		DLOG("Failed to force nvram sync\n");
12415 	}
12416 	gRootDomain->swd_lock = 0;
12417 }
12418 
12419 void
12420 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12421 {
12422 	swd_hdr *                hdr = NULL;
12423 	int                      cnt = 0;
12424 	int                      max_cnt;
12425 	pid_t                    pid = 0;
12426 	kern_return_t            kr = KERN_SUCCESS;
12427 	uint64_t                 flags;
12428 
12429 	char *                   dstAddr;
12430 	uint32_t                 size;
12431 	uint32_t                 bytesRemaining;
12432 	unsigned                 bytesWritten = 0;
12433 
12434 	char                     failureStr[512];
12435 	thread_t                 thread = NULL;
12436 	const char *             swfPanic = "swfPanic";
12437 
12438 	uint32_t                 bufSize;
12439 	int                      success = 0;
12440 
12441 #if defined(__i386__) || defined(__x86_64__)
12442 	const bool               concise = false;
12443 #else
12444 	const bool               concise = true;
12445 #endif
12446 
12447 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12448 		return;
12449 	}
12450 
12451 	failureStr[0] = 0;
12452 	if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12453 		return;
12454 	}
12455 
12456 	if (wdogTrigger) {
12457 		getFailureData(&thread, failureStr, sizeof(failureStr));
12458 
12459 		if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12460 			goto skip_stackshot;
12461 		}
12462 	} else {
12463 		AbsoluteTime now;
12464 		uint64_t nsec;
12465 		clock_get_uptime(&now);
12466 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12467 		absolutetime_to_nanoseconds(now, &nsec);
12468 		snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12469 	}
12470 
12471 	if (swd_buffer == NULL) {
12472 		sleepWakeDebugMemAlloc();
12473 		if (swd_buffer == NULL) {
12474 			return;
12475 		}
12476 	}
12477 	hdr = (swd_hdr *)swd_buffer;
12478 	bufSize = hdr->alloc_size;
12479 
12480 	dstAddr = (char*)hdr + hdr->spindump_offset;
12481 	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;
12482 
12483 	/* If not wdogTrigger only take kernel tasks stackshot
12484 	 */
12485 	if (wdogTrigger) {
12486 		pid = -1;
12487 		max_cnt = 3;
12488 	} else {
12489 		pid = 0;
12490 		max_cnt = 2;
12491 	}
12492 
12493 	/* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12494 	 * If we run out of space, take stackshot with only kernel task
12495 	 */
12496 	while (success == 0 && cnt < max_cnt) {
12497 		bytesRemaining = bufSize - hdr->spindump_offset;
12498 		cnt++;
12499 		DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12500 
12501 		size = bytesRemaining;
12502 		kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12503 		DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12504 		    kr, pid, size, flags, bytesWritten);
12505 		if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12506 			if (pid == -1) {
12507 				pid = 0;
12508 			} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12509 				flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12510 			} else {
12511 				LOG("Insufficient buffer size for only kernel task\n");
12512 				break;
12513 			}
12514 		}
12515 		if (kr == KERN_SUCCESS) {
12516 			if (bytesWritten == 0) {
12517 				MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12518 				continue;
12519 			}
12520 			bytesRemaining -= bytesWritten;
12521 			hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12522 
12523 			memset(hdr->reason, 0x20, sizeof(hdr->reason));
12524 
12525 			// Compress stackshot and save to NVRAM
12526 			{
12527 				char *outbuf = (char *)swd_compressed_buffer;
12528 				int outlen = 0;
12529 				int num_chunks = 0;
12530 				int max_chunks = 0;
12531 				int leftover = 0;
12532 				char nvram_var_name_buffer[20];
12533 
12534 				outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
12535 
12536 				if (outlen) {
12537 					max_chunks = outlen / (2096 - 200);
12538 					leftover = outlen % (2096 - 200);
12539 
12540 					if (max_chunks < 8) {
12541 						for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
12542 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12543 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
12544 								LOG("Failed to update NVRAM %d\n", num_chunks);
12545 								break;
12546 							}
12547 						}
12548 						if (leftover) {
12549 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
12550 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
12551 								LOG("Failed to update NVRAM with leftovers\n");
12552 							}
12553 						}
12554 						success = 1;
12555 						LOG("Successfully saved stackshot to NVRAM\n");
12556 					} else {
12557 						if (pid == -1) {
12558 							LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
12559 							pid = 0;
12560 						} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12561 							LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
12562 							flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12563 						} else {
12564 							LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
12565 							break;
12566 						}
12567 					}
12568 				}
12569 			}
12570 		}
12571 	}
12572 
12573 	if (failureStr[0]) {
12574 		// append sleep-wake failure code
12575 		char traceCode[80];
12576 		snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
12577 		    pmTracer->getTraceData(), pmTracer->getTracePhase());
12578 		strlcat(failureStr, traceCode, sizeof(failureStr));
12579 		if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
12580 			DLOG("Failed to write SleepWake failure string\n");
12581 		}
12582 	}
12583 
12584 	// force NVRAM sync
12585 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12586 		DLOG("Failed to force nvram sync\n");
12587 	}
12588 
12589 skip_stackshot:
12590 	if (wdogTrigger) {
12591 		if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
12592 			if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
12593 				// If current boot is due to this watch dog trigger restart in previous boot,
12594 				// then don't trigger again until at least 1 successful sleep & wake.
12595 				if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
12596 					LOG("Shutting down due to repeated Sleep/Wake failures\n");
12597 					updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12598 					PEHaltRestart(kPEHaltCPU);
12599 					return;
12600 				}
12601 			}
12602 			if (gSwdPanic == 0) {
12603 				LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
12604 				updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
12605 				PEHaltRestart(kPERestartCPU);
12606 			}
12607 		}
12608 		if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
12609 			DLOG("Failed to write SleepWake failure panic key\n");
12610 		}
12611 #if defined(__x86_64__)
12612 		if (thread) {
12613 			panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
12614 		} else
12615 #endif /* defined(__x86_64__) */
12616 		{
12617 			panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
12618 		}
12619 	} else {
12620 		gRootDomain->swd_lock = 0;
12621 		return;
12622 	}
12623 }
12624 
12625 void
12626 IOPMrootDomain::sleepWakeDebugMemAlloc()
12627 {
12628 	vm_size_t    size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
12629 
12630 	swd_hdr      *hdr = NULL;
12631 	void         *bufPtr = NULL;
12632 
12633 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12634 
12635 
12636 	if (kIOSleepWakeWdogOff & gIOKitDebug) {
12637 		return;
12638 	}
12639 
12640 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12641 		return;
12642 	}
12643 
12644 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12645 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12646 		size);
12647 	if (memDesc == NULL) {
12648 		DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
12649 		goto exit;
12650 	}
12651 
12652 	bufPtr = memDesc->getBytesNoCopy();
12653 
12654 	// Carve out memory for zlib routines
12655 	swd_zs_zmem = (vm_offset_t)bufPtr;
12656 	bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
12657 
12658 	// Carve out memory for compressed stackshots
12659 	swd_compressed_buffer = bufPtr;
12660 	bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
12661 
12662 	// Remaining is used for holding stackshot
12663 	hdr = (swd_hdr *)bufPtr;
12664 	memset(hdr, 0, sizeof(swd_hdr));
12665 
12666 	hdr->signature = SWD_HDR_SIGNATURE;
12667 	hdr->alloc_size = SWD_STACKSHOT_SIZE;
12668 
12669 	hdr->spindump_offset = sizeof(swd_hdr);
12670 	swd_buffer = (void *)hdr;
12671 	swd_memDesc = os::move(memDesc);
12672 	DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
12673 
12674 exit:
12675 	gRootDomain->swd_lock = 0;
12676 }
12677 
12678 void
12679 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
12680 {
12681 #if UNUSED
12682 	vm_size_t    size = SWD_SPINDUMP_SIZE;
12683 
12684 	swd_hdr      *hdr = NULL;
12685 
12686 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
12687 
12688 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12689 		return;
12690 	}
12691 
12692 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
12693 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
12694 		SWD_SPINDUMP_SIZE);
12695 
12696 	if (memDesc == NULL) {
12697 		DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
12698 		goto exit;
12699 	}
12700 
12701 
12702 	hdr = (swd_hdr *)memDesc->getBytesNoCopy();
12703 	memset(hdr, 0, sizeof(swd_hdr));
12704 
12705 	hdr->signature = SWD_HDR_SIGNATURE;
12706 	hdr->alloc_size = size;
12707 
12708 	hdr->spindump_offset = sizeof(swd_hdr);
12709 	swd_spindump_buffer = (void *)hdr;
12710 	swd_spindump_memDesc = os::move(memDesc);
12711 
12712 exit:
12713 	gRootDomain->swd_lock = 0;
12714 #endif /* UNUSED */
12715 }
12716 
12717 void
12718 IOPMrootDomain::sleepWakeDebugEnableWdog()
12719 {
12720 }
12721 
12722 bool
12723 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12724 {
12725 	return !systemBooting && !systemShutdown && !gWillShutdown;
12726 }
12727 
12728 void
12729 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12730 {
12731 	swd_hdr *hdr = NULL;
12732 	errno_t error = EIO;
12733 
12734 	if (swd_spindump_buffer && gSpinDumpBufferFull) {
12735 		hdr = (swd_hdr *)swd_spindump_buffer;
12736 
12737 		error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
12738 		    (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
12739 
12740 		if (error) {
12741 			return;
12742 		}
12743 
12744 		sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
12745 		    (char*)hdr + offsetof(swd_hdr, UUID),
12746 		    sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
12747 
12748 		gSpinDumpBufferFull = false;
12749 	}
12750 }
12751 
12752 errno_t
12753 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12754 {
12755 	struct vnode         *vp = NULL;
12756 	vfs_context_t        ctx = vfs_context_create(vfs_context_current());
12757 	kauth_cred_t         cred = vfs_context_ucred(ctx);
12758 	struct vnode_attr    va;
12759 	errno_t      error = EIO;
12760 
12761 	if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
12762 	    S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
12763 		LOG("Failed to open the file %s\n", name);
12764 		swd_flags |= SWD_FILEOP_ERROR;
12765 		goto exit;
12766 	}
12767 	VATTR_INIT(&va);
12768 	VATTR_WANTED(&va, va_nlink);
12769 	/* Don't dump to non-regular files or files with links. */
12770 	if (vp->v_type != VREG ||
12771 	    vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
12772 		LOG("Bailing as this is not a regular file\n");
12773 		swd_flags |= SWD_FILEOP_ERROR;
12774 		goto exit;
12775 	}
12776 	VATTR_INIT(&va);
12777 	VATTR_SET(&va, va_data_size, 0);
12778 	vnode_setattr(vp, &va, ctx);
12779 
12780 
12781 	if (buf != NULL) {
12782 		error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
12783 		    UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
12784 		if (error != 0) {
12785 			LOG("Failed to save sleep wake log. err 0x%x\n", error);
12786 			swd_flags |= SWD_FILEOP_ERROR;
12787 		} else {
12788 			DLOG("Saved %d bytes to file %s\n", len, name);
12789 		}
12790 	}
12791 
12792 exit:
12793 	if (vp) {
12794 		vnode_close(vp, FWRITE, ctx);
12795 	}
12796 	if (ctx) {
12797 		vfs_context_rele(ctx);
12798 	}
12799 
12800 	return error;
12801 }
12802 
12803 #else /* defined(__i386__) || defined(__x86_64__) */
12804 
12805 void
12806 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
12807 {
12808 	if (restart) {
12809 		if (gSwdPanic == 0) {
12810 			return;
12811 		}
12812 		panic("Sleep/Wake hang detected");
12813 		return;
12814 	}
12815 }
12816 
12817 void
12818 IOPMrootDomain::takeStackshot(bool restart)
12819 {
12820 #pragma unused(restart)
12821 }
12822 
12823 void
12824 IOPMrootDomain::deleteStackshot()
12825 {
12826 }
12827 
12828 void
12829 IOPMrootDomain::sleepWakeDebugMemAlloc()
12830 {
12831 }
12832 
12833 void
12834 IOPMrootDomain::saveFailureData2File()
12835 {
12836 }
12837 
12838 void
12839 IOPMrootDomain::sleepWakeDebugEnableWdog()
12840 {
12841 }
12842 
12843 bool
12844 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
12845 {
12846 	return false;
12847 }
12848 
12849 void
12850 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
12851 {
12852 }
12853 
12854 errno_t
12855 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
12856 {
12857 	return 0;
12858 }
12859 
12860 #endif /* defined(__i386__) || defined(__x86_64__) */
12861 
12862