xref: /xnu-12377.41.6/iokit/Kernel/IOPMrootDomain.cpp (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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 <IOKit/IOBSD.h>
60 #include "IOKitKernelInternal.h"
61 #if HIBERNATION
62 #include <IOKit/IOHibernatePrivate.h>
63 #endif /* HIBERNATION */
64 #include <machine/machine_routines.h>
65 #include <console/video_console.h>
66 #include <sys/syslog.h>
67 #include <sys/sysctl.h>
68 #include <sys/vnode.h>
69 #include <sys/vnode_internal.h>
70 #include <sys/fcntl.h>
71 #include <os/log.h>
72 #include <pexpert/device_tree.h>
73 #include <pexpert/protos.h>
74 #include <AssertMacros.h>
75 
76 #include <sys/time.h>
77 #include "IOServicePrivate.h"   // _IOServiceInterestNotifier
78 #include "IOServicePMPrivate.h"
79 
80 #include <libkern/zlib.h>
81 #include <os/cpp_util.h>
82 #include <os/atomic_private.h>
83 #include <libkern/c++/OSBoundedArrayRef.h>
84 
85 #if DEVELOPMENT || DEBUG
86 #include <os/system_event_log.h>
87 #endif /* DEVELOPMENT || DEBUG */
88 
89 __BEGIN_DECLS
90 #include <mach/shared_region.h>
91 #include <kern/clock.h>
92 #include <vm/vm_pageout_xnu.h>
93 __END_DECLS
94 
95 #if defined(__i386__) || defined(__x86_64__)
96 __BEGIN_DECLS
97 #include "IOPMrootDomainInternal.h"
98 const char *processor_to_datastring(const char *prefix, processor_t target_processor);
99 __END_DECLS
100 #endif
101 
102 #define kIOPMrootDomainClass    "IOPMrootDomain"
103 #define LOG_PREFIX              "PMRD: "
104 
105 
106 #define MSG(x...) \
107     do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
108 
109 #define LOG(x...)    \
110     do { kprintf(LOG_PREFIX x); } while (false)
111 
112 #if DEVELOPMENT || DEBUG
113 #define DEBUG_LOG(x...) do { \
114     if (kIOLogPMRootDomain & gIOKitDebug) \
115     kprintf(LOG_PREFIX x); \
116     os_log_debug(OS_LOG_DEFAULT, LOG_PREFIX x); \
117 } while (false)
118 #else
119 #define DEBUG_LOG(x...)
120 #endif
121 
122 #define DLOG(x...)  do { \
123     if (kIOLogPMRootDomain & gIOKitDebug) \
124 	IOLog(LOG_PREFIX x); \
125     else \
126 	os_log(OS_LOG_DEFAULT, LOG_PREFIX x); \
127 } while (false)
128 
129 #define DMSG(x...)  do { \
130     if (kIOLogPMRootDomain & gIOKitDebug) { \
131 	kprintf(LOG_PREFIX x); \
132     } \
133 } while (false)
134 
135 
136 #define _LOG(x...)
137 
138 #define CHECK_THREAD_CONTEXT
139 #ifdef  CHECK_THREAD_CONTEXT
140 static IOWorkLoop * gIOPMWorkLoop = NULL;
141 #define ASSERT_GATED()                                      \
142 do {                                                        \
143     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
144 	panic("RootDomain: not inside PM gate");            \
145     }                                                       \
146 } while(false)
147 #else
148 #define ASSERT_GATED()
149 #endif /* CHECK_THREAD_CONTEXT */
150 
151 #define CAP_LOSS(c)  \
152 	(((_pendingCapability & (c)) == 0) && \
153 	 ((_currentCapability & (c)) != 0))
154 
155 #define CAP_GAIN(c)  \
156 	(((_currentCapability & (c)) == 0) && \
157 	 ((_pendingCapability & (c)) != 0))
158 
159 #define CAP_CHANGE(c)    \
160 	(((_currentCapability ^ _pendingCapability) & (c)) != 0)
161 
162 #define CAP_CURRENT(c)  \
163 	((_currentCapability & (c)) != 0)
164 
165 #define CAP_HIGHEST(c)  \
166 	((_highestCapability & (c)) != 0)
167 
168 #define CAP_PENDING(c)  \
169 	((_pendingCapability & (c)) != 0)
170 
171 // rdar://problem/9157444
172 #if defined(__i386__) || defined(__x86_64__)
173 #define DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY   20
174 #endif
175 
176 // Event types for IOPMPowerStateQueue::submitPowerEvent()
177 enum {
178 	kPowerEventFeatureChanged = 1,             // 1
179 	kPowerEventReceivedPowerNotification,      // 2
180 	kPowerEventSystemBootCompleted,            // 3
181 	kPowerEventSystemShutdown,                 // 4
182 	kPowerEventUserDisabledSleep,              // 5
183 	kPowerEventRegisterSystemCapabilityClient, // 6
184 	kPowerEventRegisterKernelCapabilityClient, // 7
185 	kPowerEventPolicyStimulus,                 // 8
186 	kPowerEventAssertionCreate,                // 9
187 	kPowerEventAssertionRelease,               // 10
188 	kPowerEventAssertionSetLevel,              // 11
189 	kPowerEventQueueSleepWakeUUID,             // 12
190 	kPowerEventPublishSleepWakeUUID,           // 13
191 	kPowerEventSetDisplayPowerOn,              // 14
192 	kPowerEventPublishWakeType,                // 15
193 	kPowerEventAOTEvaluate,                    // 16
194 	kPowerEventRunModeRequest                  // 17
195 };
196 
197 // For evaluatePolicy()
198 // List of stimuli that affects the root domain policy.
199 enum {
200 	kStimulusDisplayWranglerSleep,      // 0
201 	kStimulusDisplayWranglerWake,       // 1
202 	kStimulusAggressivenessChanged,     // 2
203 	kStimulusDemandSystemSleep,         // 3
204 	kStimulusAllowSystemSleepChanged,   // 4
205 	kStimulusDarkWakeActivityTickle,    // 5
206 	kStimulusDarkWakeEntry,             // 6
207 	kStimulusDarkWakeReentry,           // 7
208 	kStimulusDarkWakeEvaluate,          // 8
209 	kStimulusNoIdleSleepPreventers,     // 9
210 	kStimulusEnterUserActiveState,      // 10
211 	kStimulusLeaveUserActiveState       // 11
212 };
213 
214 // Internal power state change reasons
215 // Must be less than kIOPMSleepReasonClamshell=101
216 enum {
217 	kCPSReasonNone = 0,                 // 0
218 	kCPSReasonInit,                     // 1
219 	kCPSReasonWake,                     // 2
220 	kCPSReasonIdleSleepPrevent,         // 3
221 	kCPSReasonIdleSleepAllow,           // 4
222 	kCPSReasonPowerOverride,            // 5
223 	kCPSReasonPowerDownCancel,          // 6
224 	kCPSReasonAOTExit,                  // 7
225 	kCPSReasonAdjustPowerState,         // 8
226 	kCPSReasonDarkWakeCannotSleep,      // 9
227 	kCPSReasonIdleSleepEnabled,         // 10
228 	kCPSReasonEvaluatePolicy,           // 11
229 	kCPSReasonSustainFullWake,          // 12
230 	kCPSReasonPMInternals = (kIOPMSleepReasonClamshell - 1)
231 };
232 
233 extern "C" {
234 IOReturn OSKextSystemSleepOrWake( UInt32 );
235 }
236 extern "C" ppnum_t      pmap_find_phys(pmap_t pmap, addr64_t va);
237 extern "C" addr64_t     kvtophys(vm_offset_t va);
238 extern "C" boolean_t    kdp_has_polled_corefile();
239 
240 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
241 static void notifySystemShutdown( IOService * root, uint32_t messageType );
242 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
243 static void pmEventTimeStamp(uint64_t *recordTS);
244 static void powerButtonUpCallout( thread_call_param_t, thread_call_param_t );
245 static void powerButtonDownCallout( thread_call_param_t, thread_call_param_t );
246 static OSPtr<const OSSymbol> copyKextIdentifierWithAddress(vm_address_t address);
247 
248 static int  IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt);
249 static clock_sec_t IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt);
250 #define YMDTF       "%04d/%02d/%d %02d:%02d:%02d"
251 #define YMDT(cal)   ((int)(cal)->year), (cal)->month, (cal)->day, (cal)->hour, (cal)->minute, (cal)->second
252 
253 // "IOPMSetSleepSupported"  callPlatformFunction name
254 static OSSharedPtr<const OSSymbol>         sleepSupportedPEFunction;
255 static OSSharedPtr<const OSSymbol>         sleepMessagePEFunction;
256 static OSSharedPtr<const OSSymbol>         gIOPMWakeTypeUserKey;
257 
258 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalConnectedKey;
259 static OSSharedPtr<const OSSymbol>         gIOPMPSExternalChargeCapableKey;
260 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryInstalledKey;
261 static OSSharedPtr<const OSSymbol>         gIOPMPSIsChargingKey;
262 static OSSharedPtr<const OSSymbol>         gIOPMPSAtWarnLevelKey;
263 static OSSharedPtr<const OSSymbol>         gIOPMPSAtCriticalLevelKey;
264 static OSSharedPtr<const OSSymbol>         gIOPMPSCurrentCapacityKey;
265 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxCapacityKey;
266 static OSSharedPtr<const OSSymbol>         gIOPMPSDesignCapacityKey;
267 static OSSharedPtr<const OSSymbol>         gIOPMPSTimeRemainingKey;
268 static OSSharedPtr<const OSSymbol>         gIOPMPSAmperageKey;
269 static OSSharedPtr<const OSSymbol>         gIOPMPSVoltageKey;
270 static OSSharedPtr<const OSSymbol>         gIOPMPSCycleCountKey;
271 static OSSharedPtr<const OSSymbol>         gIOPMPSMaxErrKey;
272 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterInfoKey;
273 static OSSharedPtr<const OSSymbol>         gIOPMPSLocationKey;
274 static OSSharedPtr<const OSSymbol>         gIOPMPSErrorConditionKey;
275 static OSSharedPtr<const OSSymbol>         gIOPMPSManufacturerKey;
276 static OSSharedPtr<const OSSymbol>         gIOPMPSManufactureDateKey;
277 static OSSharedPtr<const OSSymbol>         gIOPMPSModelKey;
278 static OSSharedPtr<const OSSymbol>         gIOPMPSSerialKey;
279 static OSSharedPtr<const OSSymbol>         gIOPMPSLegacyBatteryInfoKey;
280 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryHealthKey;
281 static OSSharedPtr<const OSSymbol>         gIOPMPSHealthConfidenceKey;
282 static OSSharedPtr<const OSSymbol>         gIOPMPSCapacityEstimatedKey;
283 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryChargeStatusKey;
284 static OSSharedPtr<const OSSymbol>         gIOPMPSBatteryTemperatureKey;
285 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsKey;
286 static OSSharedPtr<const OSSymbol>         gIOPMPSChargerConfigurationKey;
287 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsIDKey;
288 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsWattsKey;
289 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsRevisionKey;
290 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSerialNumberKey;
291 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsFamilyKey;
292 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsAmperageKey;
293 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsDescriptionKey;
294 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsPMUConfigurationKey;
295 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSourceIDKey;
296 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsErrorFlagsKey;
297 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsSharedSourceKey;
298 static OSSharedPtr<const OSSymbol>         gIOPMPSAdapterDetailsCloakedKey;
299 static OSSharedPtr<const OSSymbol>         gIOPMPSInvalidWakeSecondsKey;
300 static OSSharedPtr<const OSSymbol>         gIOPMPSPostChargeWaitSecondsKey;
301 static OSSharedPtr<const OSSymbol>         gIOPMPSPostDishargeWaitSecondsKey;
302 
303 #define kIOSleepSupportedKey        "IOSleepSupported"
304 #define kIOPMSystemCapabilitiesKey  "System Capabilities"
305 #define kIOPMSystemDefaultOverrideKey   "SystemPowerProfileOverrideDict"
306 
307 #define kIORequestWranglerIdleKey   "IORequestIdle"
308 #define kDefaultWranglerIdlePeriod  1000 // in milliseconds
309 
310 #define kIOSleepWakeFailureString   "SleepWakeFailureString"
311 #define kIOEFIBootRomFailureKey     "wake-failure"
312 #define kIOSleepWakeFailurePanic    "SleepWakeFailurePanic"
313 
314 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
315 	                   | kIOPMSupportedOnBatt \
316 	                   | kIOPMSupportedOnUPS)
317 
318 #define kLocalEvalClamshellCommand  (1 << 15)
319 #define kIdleSleepRetryInterval     (3 * 60 * 1000)
320 
321 // Minimum time in milliseconds after AP wake that we allow idle timer to expire.
322 // We impose this minimum to avoid race conditions in the AP wake path where
323 // userspace clients are not able to acquire power assertions before the idle timer expires.
324 #if XNU_TARGET_OS_IOS
325 #define kMinimumTimeBeforeIdleSleep     3000
326 #else
327 #define kMinimumTimeBeforeIdleSleep     1000
328 #endif
329 
330 #define DISPLAY_WRANGLER_PRESENT    (!NO_KERNEL_HID)
331 
332 enum {
333 	kWranglerPowerStateMin   = 0,
334 	kWranglerPowerStateSleep = 2,
335 	kWranglerPowerStateDim   = 3,
336 	kWranglerPowerStateMax   = 4
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 uint64_t gShutdownTime;
621 static bool gWakeReasonSysctlRegistered = false;
622 static bool gBootReasonSysctlRegistered = false;
623 static bool gShutdownReasonSysctlRegistered = false;
624 static bool gWillShutdownSysctlRegistered = false;
625 static AbsoluteTime gUserActiveAbsTime;
626 static AbsoluteTime gUserInactiveAbsTime;
627 
628 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
629 static bool gSpinDumpBufferFull = false;
630 #endif
631 
632 z_stream          swd_zs;
633 vm_offset_t swd_zs_zmem;
634 //size_t swd_zs_zsize;
635 size_t swd_zs_zoffset;
636 #if defined(__i386__) || defined(__x86_64__)
637 IOCPU *currentShutdownTarget = NULL;
638 #endif
639 
640 static unsigned int     gPMHaltBusyCount;
641 static unsigned int     gPMHaltIdleCount;
642 static int              gPMHaltDepth;
643 static uint32_t         gPMHaltMessageType;
644 static IOLock *         gPMHaltLock  = NULL;
645 static OSSharedPtr<OSArray>        gPMHaltArray;
646 static OSSharedPtr<const OSSymbol> gPMHaltClientAcknowledgeKey;
647 static bool             gPMQuiesced;
648 
649 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
650 #define kCPUUnknownIndex    9999999
651 enum {
652 	kInformAC = 0,
653 	kInformLid = 1,
654 	kInformableCount = 2
655 };
656 
657 OSSharedPtr<const OSSymbol> gIOPMStatsResponseTimedOut;
658 OSSharedPtr<const OSSymbol> gIOPMStatsResponseCancel;
659 OSSharedPtr<const OSSymbol> gIOPMStatsResponseSlow;
660 OSSharedPtr<const OSSymbol> gIOPMStatsResponsePrompt;
661 OSSharedPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow;
662 
663 #define kBadPMFeatureID     0
664 
665 /*
666  * PMSettingHandle
667  * Opaque handle passed to clients of registerPMSettingController()
668  */
669 class PMSettingHandle : public OSObject
670 {
671 	OSDeclareFinalStructors( PMSettingHandle );
672 	friend class PMSettingObject;
673 
674 private:
675 	PMSettingObject *pmso;
676 	void free(void) APPLE_KEXT_OVERRIDE;
677 };
678 
679 /*
680  * PMSettingObject
681  * Internal object to track each PM setting controller
682  */
683 class PMSettingObject : public OSObject
684 {
685 	OSDeclareFinalStructors( PMSettingObject );
686 	friend class IOPMrootDomain;
687 
688 private:
689 	queue_head_t                    calloutQueue;
690 	thread_t                        waitThread;
691 	IOPMrootDomain                  *parent;
692 	PMSettingHandle                 *pmsh;
693 	IOPMSettingControllerCallback   func;
694 	OSObject                        *target;
695 	uintptr_t                       refcon;
696 	OSDataAllocation<uint32_t>      publishedFeatureID;
697 	uint32_t                        settingCount;
698 	bool                            disabled;
699 
700 	void free(void) APPLE_KEXT_OVERRIDE;
701 
702 public:
703 	static PMSettingObject *pmSettingObject(
704 		IOPMrootDomain                  *parent_arg,
705 		IOPMSettingControllerCallback   handler_arg,
706 		OSObject                        *target_arg,
707 		uintptr_t                       refcon_arg,
708 		uint32_t                        supportedPowerSources,
709 		const OSSymbol                  *settings[],
710 		OSObject                        **handle_obj);
711 
712 	IOReturn dispatchPMSetting(const OSSymbol *type, OSObject *object);
713 	void clientHandleFreed(void);
714 };
715 
716 struct PMSettingCallEntry {
717 	queue_chain_t   link;
718 	thread_t        thread;
719 };
720 
721 #define PMSETTING_LOCK()    IOLockLock(settingsCtrlLock)
722 #define PMSETTING_UNLOCK()  IOLockUnlock(settingsCtrlLock)
723 #define PMSETTING_WAIT(p)   IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
724 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
725 
726 /*
727  * PMTraceWorker
728  * Internal helper object for logging trace points to RTC
729  * IOPMrootDomain and only IOPMrootDomain should instantiate
730  * exactly one of these.
731  */
732 
733 typedef void (*IOPMTracePointHandler)(
734 	void * target, uint32_t code, uint32_t data );
735 
736 class PMTraceWorker : public OSObject
737 {
738 	OSDeclareDefaultStructors(PMTraceWorker);
739 public:
740 	typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
741 
742 	static OSPtr<PMTraceWorker> tracer( IOPMrootDomain * );
743 	void                        tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
744 	void                        tracePoint(uint8_t phase);
745 	void                        traceDetail(uint32_t detail);
746 	void                        traceComponentWakeProgress(uint32_t component, uint32_t data);
747 	int                         recordTopLevelPCIDevice(IOService *);
748 	void                        RTC_TRACE(void);
749 	virtual bool                serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
750 
751 	IOPMTracePointHandler       tracePointHandler;
752 	void *                      tracePointTarget;
753 	uint64_t                    getPMStatusCode();
754 	uint8_t                     getTracePhase();
755 	uint32_t                    getTraceData();
756 private:
757 	IOPMrootDomain              *owner;
758 	IOLock                      *pmTraceWorkerLock;
759 	OSSharedPtr<OSArray>         pciDeviceBitMappings;
760 
761 	uint8_t                     addedToRegistry;
762 	uint8_t                     tracePhase;
763 	uint32_t                    traceData32;
764 	uint8_t                     loginWindowData;
765 	uint8_t                     coreDisplayData;
766 	uint8_t                     coreGraphicsData;
767 };
768 
769 /*
770  * this should be treated as POD, as it's byte-copied around
771  * and we cannot rely on d'tor firing at the right time
772  */
773 struct PMAssertStruct {
774 	IOPMDriverAssertionID       id;
775 	IOPMDriverAssertionType     assertionBits;
776 	uint64_t                    createdTime;
777 	uint64_t                    modifiedTime;
778 	const OSSymbol              *ownerString;
779 	IOService                   *ownerService;
780 	uint64_t                    registryEntryID;
781 	IOPMDriverAssertionLevel    level;
782 	uint64_t                    assertCPUStartTime;
783 	uint64_t                    assertCPUDuration;
784 };
785 OSDefineValueObjectForDependentType(PMAssertStruct)
786 
787 /*
788  * PMAssertionsTracker
789  * Tracks kernel and user space PM assertions
790  */
791 class PMAssertionsTracker : public OSObject
792 {
793 	OSDeclareFinalStructors(PMAssertionsTracker);
794 public:
795 	static PMAssertionsTracker  *pmAssertionsTracker( IOPMrootDomain * );
796 
797 	IOReturn                    createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
798 	IOReturn                    releaseAssertion(IOPMDriverAssertionID);
799 	IOReturn                    setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
800 	IOReturn                    setUserAssertionLevels(IOPMDriverAssertionType);
801 
802 	OSSharedPtr<OSArray>        copyAssertionsArray(void);
803 	IOPMDriverAssertionType     getActivatedAssertions(void);
804 	IOPMDriverAssertionLevel    getAssertionLevel(IOPMDriverAssertionType);
805 
806 	IOReturn                    handleCreateAssertion(OSValueObject<PMAssertStruct> *);
807 	IOReturn                    handleReleaseAssertion(IOPMDriverAssertionID);
808 	IOReturn                    handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
809 	IOReturn                    handleSetUserAssertionLevels(void * arg0);
810 	void                        publishProperties(void);
811 	void                        reportCPUBitAccounting(void);
812 	PMAssertStruct              *detailsForID(IOPMDriverAssertionID, int *);
813 
814 private:
815 	uint32_t                    tabulateProducerCount;
816 	uint32_t                    tabulateConsumerCount;
817 
818 	uint64_t                    maxAssertCPUDuration;
819 	uint64_t                    maxAssertCPUEntryId;
820 
821 	void                        tabulate(void);
822 	void                        updateCPUBitAccounting(PMAssertStruct * assertStruct);
823 
824 	IOPMrootDomain              *owner;
825 	OSSharedPtr<OSArray>        assertionsArray;
826 	IOLock                      *assertionsArrayLock;
827 	IOPMDriverAssertionID       issuingUniqueID __attribute__((aligned(8)));/* aligned for atomic access */
828 	IOPMDriverAssertionType     assertionsKernel;
829 	IOPMDriverAssertionType     assertionsUser;
830 	IOPMDriverAssertionType     assertionsCombined;
831 };
832 
833 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
834 
835 /*
836  * PMHaltWorker
837  * Internal helper object for Shutdown/Restart notifications.
838  */
839 #define kPMHaltMaxWorkers   8
840 #define kPMHaltTimeoutMS    100
841 
842 class PMHaltWorker : public OSObject
843 {
844 	OSDeclareFinalStructors( PMHaltWorker );
845 
846 public:
847 	IOService *  service;// service being worked on
848 	AbsoluteTime startTime; // time when work started
849 	int          depth;  // work on nubs at this PM-tree depth
850 	int          visits; // number of nodes visited (debug)
851 	IOLock *     lock;
852 	bool         timeout;// service took too long
853 
854 	static  PMHaltWorker * worker( void );
855 	static  void main( void * arg, wait_result_t waitResult );
856 	static  void work( PMHaltWorker * me );
857 	static  void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
858 	virtual void free( void ) APPLE_KEXT_OVERRIDE;
859 };
860 
OSDefineMetaClassAndFinalStructors(PMHaltWorker,OSObject)861 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
862 
863 
864 #define super IOService
865 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
866 
867 boolean_t
868 IOPMRootDomainGetWillShutdown(void)
869 {
870 	return gWillShutdown != 0;
871 }
872 
873 static void
IOPMRootDomainWillShutdown(void)874 IOPMRootDomainWillShutdown(void)
875 {
876 	if (OSCompareAndSwap(0, 1, &gWillShutdown)) {
877 		IOService::willShutdown();
878 		for (int i = 0; i < 100; i++) {
879 			if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) {
880 				break;
881 			}
882 			IOSleep( 100 );
883 		}
884 	}
885 }
886 
887 extern "C" IONotifier *
registerSleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)888 registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
889 {
890 	return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ).detach();
891 }
892 
893 extern "C" IONotifier *
registerPrioritySleepWakeInterest(IOServiceInterestHandler handler,void * self,void * ref)894 registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
895 {
896 	return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ).detach();
897 }
898 
899 extern "C" IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon)900 acknowledgeSleepWakeNotification(void * PMrefcon)
901 {
902 	return gRootDomain->allowPowerChange((unsigned long)PMrefcon );
903 }
904 
905 extern "C" IOReturn
vetoSleepWakeNotification(void * PMrefcon)906 vetoSleepWakeNotification(void * PMrefcon)
907 {
908 	return gRootDomain->cancelPowerChange((unsigned long)PMrefcon );
909 }
910 
911 extern "C" IOReturn
rootDomainRestart(void)912 rootDomainRestart( void )
913 {
914 	return gRootDomain->restartSystem();
915 }
916 
917 extern "C" IOReturn
rootDomainShutdown(void)918 rootDomainShutdown( void )
919 {
920 	return gRootDomain->shutdownSystem();
921 }
922 
923 static void
halt_log_putc(char c)924 halt_log_putc(char c)
925 {
926 	if (gHaltLogPos >= (kHaltLogSize - 2)) {
927 		return;
928 	}
929 	gHaltLog[gHaltLogPos++] = c;
930 }
931 
932 extern "C" void
933 _doprnt_log(const char     *fmt,
934     va_list                 *argp,
935     void                    (*putc)(char),
936     int                     radix);
937 
938 static int
halt_log(const char * fmt,...)939 halt_log(const char *fmt, ...)
940 {
941 	va_list listp;
942 
943 	va_start(listp, fmt);
944 	_doprnt_log(fmt, &listp, &halt_log_putc, 16);
945 	va_end(listp);
946 
947 	return 0;
948 }
949 
950 extern "C" void
halt_log_enter(const char * what,const void * pc,uint64_t time)951 halt_log_enter(const char * what, const void * pc, uint64_t time)
952 {
953 	uint64_t nano, millis;
954 
955 	if (!gHaltLog) {
956 		return;
957 	}
958 	absolutetime_to_nanoseconds(time, &nano);
959 	millis = nano / NSEC_PER_MSEC;
960 	if (millis < 100) {
961 		return;
962 	}
963 
964 	IOLockLock(gHaltLogLock);
965 	if (pc) {
966 		halt_log("%s: %qd ms @ 0x%lx, ", what, millis, VM_KERNEL_UNSLIDE(pc));
967 		OSKext::printKextsInBacktrace((vm_offset_t *) &pc, 1, &halt_log,
968 		    OSKext::kPrintKextsLock | OSKext::kPrintKextsUnslide | OSKext::kPrintKextsTerse);
969 	} else {
970 		halt_log("%s: %qd ms\n", what, millis);
971 	}
972 
973 	gHaltLog[gHaltLogPos] = 0;
974 	IOLockUnlock(gHaltLogLock);
975 }
976 
977 extern  uint32_t                           gFSState;
978 
979 extern "C" void
IOSystemShutdownNotification(int howto,int stage)980 IOSystemShutdownNotification(int howto, int stage)
981 {
982 	uint64_t startTime;
983 
984 	if (kIOSystemShutdownNotificationStageRootUnmount == stage) {
985 #if defined(XNU_TARGET_OS_OSX)
986 		uint64_t nano, millis;
987 		startTime = mach_absolute_time();
988 		IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
989 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
990 		millis = nano / NSEC_PER_MSEC;
991 		if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) {
992 			printf("waitQuiet() for unmount %qd ms\n", millis);
993 		}
994 #endif /* defined(XNU_TARGET_OS_OSX) */
995 		return;
996 	}
997 
998 	if (kIOSystemShutdownNotificationTerminateDEXTs == stage) {
999 		uint64_t nano, millis;
1000 		startTime = mach_absolute_time();
1001 		IOServicePH::systemHalt(howto);
1002 		absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano);
1003 		millis = nano / NSEC_PER_MSEC;
1004 		if (true || (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog))) {
1005 			printf("IOServicePH::systemHalt took %qd ms\n", millis);
1006 		}
1007 		return;
1008 	}
1009 
1010 	assert(kIOSystemShutdownNotificationStageProcessExit == stage);
1011 
1012 	IOLockLock(gHaltLogLock);
1013 	if (!gHaltLog) {
1014 		gHaltLog = IONewData(char, (vm_size_t)kHaltLogSize);
1015 		gHaltStartTime = mach_absolute_time();
1016 		if (gHaltLog) {
1017 			halt_log_putc('\n');
1018 		}
1019 	}
1020 	IOLockUnlock(gHaltLogLock);
1021 
1022 	startTime = mach_absolute_time();
1023 	IOPMRootDomainWillShutdown();
1024 	halt_log_enter("IOPMRootDomainWillShutdown", NULL, mach_absolute_time() - startTime);
1025 #if HIBERNATION
1026 	startTime = mach_absolute_time();
1027 	IOHibernateSystemPostWake(true);
1028 	halt_log_enter("IOHibernateSystemPostWake", NULL, mach_absolute_time() - startTime);
1029 #endif
1030 	if (OSCompareAndSwap(0, 1, &gPagingOff)) {
1031 		gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
1032 	}
1033 }
1034 
1035 extern "C" int sync_internal(void);
1036 
1037 /*
1038  *  A device is always in the highest power state which satisfies its driver,
1039  *  its policy-maker, and any power children it has, but within the constraint
1040  *  of the power state provided by its parent.  The driver expresses its desire by
1041  *  calling changePowerStateTo(), the policy-maker expresses its desire by calling
1042  *  changePowerStateToPriv(), and the children express their desires by calling
1043  *  requestPowerDomainState().
1044  *
1045  *  The Root Power Domain owns the policy for idle and demand sleep for the system.
1046  *  It is a power-managed IOService just like the others in the system.
1047  *  It implements several power states which map to what we see as Sleep and On.
1048  *
1049  *  The sleep policy is as follows:
1050  *  1. Sleep is prevented if the case is open so that nobody will think the machine
1051  *  is off and plug/unplug cards.
1052  *  2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
1053  *  3. System cannot Sleep if some object in the tree is in a power state marked
1054  *  kIOPMPreventSystemSleep.
1055  *
1056  *  These three conditions are enforced using the "driver clamp" by calling
1057  *  changePowerStateTo(). For example, if the case is opened,
1058  *  changePowerStateTo(ON_STATE) is called to hold the system on regardless
1059  *  of the desires of the children of the root or the state of the other clamp.
1060  *
1061  *  Demand Sleep is initiated by pressing the front panel power button, closing
1062  *  the clamshell, or selecting the menu item. In this case the root's parent
1063  *  actually initiates the power state change so that the root domain has no
1064  *  choice and does not give applications the opportunity to veto the change.
1065  *
1066  *  Idle Sleep occurs if no objects in the tree are in a state marked
1067  *  kIOPMPreventIdleSleep.  When this is true, the root's children are not holding
1068  *  the root on, so it sets the "policy-maker clamp" by calling
1069  *  changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
1070  *  This timer is set for the difference between the sleep timeout slider and the
1071  *  display dim timeout slider. When the timer expires, it releases its clamp and
1072  *  now nothing is holding it awake, so it falls asleep.
1073  *
1074  *  Demand sleep is prevented when the system is booting.  When preferences are
1075  *  transmitted by the loginwindow at the end of boot, a flag is cleared,
1076  *  and this allows subsequent Demand Sleep.
1077  */
1078 
1079 //******************************************************************************
1080 
1081 IOPMrootDomain *
construct(void)1082 IOPMrootDomain::construct( void )
1083 {
1084 	IOPMrootDomain  *root;
1085 
1086 	root = new IOPMrootDomain;
1087 	if (root) {
1088 		root->init();
1089 	}
1090 
1091 	return root;
1092 }
1093 
1094 //******************************************************************************
1095 // updateConsoleUsersCallout
1096 //
1097 //******************************************************************************
1098 
1099 static void
updateConsoleUsersCallout(thread_call_param_t p0,thread_call_param_t p1)1100 updateConsoleUsersCallout(thread_call_param_t p0, thread_call_param_t p1)
1101 {
1102 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1103 	rootDomain->updateConsoleUsers();
1104 }
1105 
1106 void
updateConsoleUsers(void)1107 IOPMrootDomain::updateConsoleUsers(void)
1108 {
1109 	IOService::updateConsoleUsers(NULL, kIOMessageSystemHasPoweredOn);
1110 	updateTasksSuspend(kTasksSuspendUnsuspended, kTasksSuspendNoChange);
1111 }
1112 
1113 bool
updateTasksSuspend(int newTasksSuspended,int newAOTTasksSuspended)1114 IOPMrootDomain::updateTasksSuspend(int newTasksSuspended, int newAOTTasksSuspended)
1115 {
1116 	bool newSuspend;
1117 
1118 	WAKEEVENT_LOCK();
1119 	if (newTasksSuspended != kTasksSuspendNoChange) {
1120 		tasksSuspended = (newTasksSuspended != kTasksSuspendUnsuspended);
1121 	}
1122 	if (newAOTTasksSuspended != kTasksSuspendNoChange) {
1123 		_aotTasksSuspended = (newAOTTasksSuspended != kTasksSuspendUnsuspended);
1124 	}
1125 	newSuspend = (tasksSuspended || _aotTasksSuspended);
1126 	if (newSuspend == tasksSuspendState) {
1127 		WAKEEVENT_UNLOCK();
1128 		return false;
1129 	}
1130 	tasksSuspendState = newSuspend;
1131 	WAKEEVENT_UNLOCK();
1132 	tasks_system_suspend(newSuspend);
1133 	return true;
1134 }
1135 
1136 //******************************************************************************
1137 
1138 static void
disk_sync_callout(thread_call_param_t p0,thread_call_param_t p1)1139 disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
1140 {
1141 	IOPMrootDomain * rootDomain = (IOPMrootDomain *) p0;
1142 	uint32_t    notifyRef  = (uint32_t)(uintptr_t) p1;
1143 	uint32_t    powerState = rootDomain->getPowerState();
1144 
1145 	DLOG("disk_sync_callout ps=%u\n", powerState);
1146 
1147 	if (ON_STATE == powerState) {
1148 		sync_internal();
1149 
1150 #if HIBERNATION
1151 		// Block sleep until trim issued on previous wake path is completed.
1152 		IOHibernateSystemPostWake(true);
1153 #endif
1154 	}
1155 #if HIBERNATION
1156 	else {
1157 		IOHibernateSystemPostWake(false);
1158 
1159 		rootDomain->sleepWakeDebugSaveSpinDumpFile();
1160 	}
1161 #endif
1162 
1163 	rootDomain->allowPowerChange(notifyRef);
1164 	DLOG("disk_sync_callout finish\n");
1165 }
1166 
1167 //******************************************************************************
1168 static UInt32
computeDeltaTimeMS(const AbsoluteTime * startTime,AbsoluteTime * elapsedTime)1169 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * elapsedTime )
1170 {
1171 	AbsoluteTime    endTime;
1172 	UInt64          nano = 0;
1173 
1174 	clock_get_uptime(&endTime);
1175 	if (CMP_ABSOLUTETIME(&endTime, startTime) <= 0) {
1176 		*elapsedTime = 0;
1177 	} else {
1178 		SUB_ABSOLUTETIME(&endTime, startTime);
1179 		absolutetime_to_nanoseconds(endTime, &nano);
1180 		*elapsedTime = endTime;
1181 	}
1182 
1183 	return (UInt32)(nano / NSEC_PER_MSEC);
1184 }
1185 
1186 //******************************************************************************
1187 
1188 static int
1189 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
1190 {
1191 	struct timeval *swt = (struct timeval *)arg1;
1192 	struct proc *p = req->p;
1193 
1194 	if (p == kernproc) {
1195 		return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
1196 	} else if (proc_is64bit(p)) {
1197 		struct user64_timeval t = {};
1198 		t.tv_sec = swt->tv_sec;
1199 		t.tv_usec = swt->tv_usec;
1200 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1201 	} else {
1202 		struct user32_timeval t = {};
1203 		t.tv_sec = (typeof(t.tv_sec))swt->tv_sec;
1204 		t.tv_usec = swt->tv_usec;
1205 		return sysctl_io_opaque(req, &t, sizeof(t), NULL);
1206 	}
1207 }
1208 
1209 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
1210     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1211     &gIOLastUserSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1212 
1213 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
1214     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1215     &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
1216 
1217 SYSCTL_QUAD(_kern, OID_AUTO, wake_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastWakeAbsTime, "");
1218 SYSCTL_QUAD(_kern, OID_AUTO, sleep_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gIOLastSleepAbsTime, "");
1219 SYSCTL_QUAD(_kern, OID_AUTO, useractive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserActiveAbsTime, "");
1220 SYSCTL_QUAD(_kern, OID_AUTO, userinactive_abs_time, CTLFLAG_RD | CTLFLAG_LOCKED, &gUserInactiveAbsTime, "");
1221 
1222 static int
1223 sysctl_willshutdown SYSCTL_HANDLER_ARGS
1224 {
1225 	int new_value, changed, error;
1226 
1227 	if (!gWillShutdownSysctlRegistered) {
1228 		return ENOENT;
1229 	}
1230 
1231 	error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
1232 	if (changed) {
1233 		if (!gWillShutdown && (new_value == 1)) {
1234 			IOPMRootDomainWillShutdown();
1235 		} else {
1236 			error = EINVAL;
1237 		}
1238 	}
1239 	return error;
1240 }
1241 
1242 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
1243     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1244     NULL, 0, sysctl_willshutdown, "I", "");
1245 
1246 #if defined(XNU_TARGET_OS_OSX)
1247 
1248 static int
sysctl_progressmeterenable(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1249 sysctl_progressmeterenable
1250 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1251 {
1252 	int error;
1253 	int new_value, changed;
1254 
1255 	error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
1256 
1257 	if (changed) {
1258 		vc_enable_progressmeter(new_value);
1259 	}
1260 
1261 	return error;
1262 }
1263 
1264 static int
sysctl_progressmeter(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1265 sysctl_progressmeter
1266 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1267 {
1268 	int error;
1269 	int new_value, changed;
1270 
1271 	error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
1272 
1273 	if (changed) {
1274 		vc_set_progressmeter(new_value);
1275 	}
1276 
1277 	return error;
1278 }
1279 
1280 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
1281     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1282     NULL, 0, sysctl_progressmeterenable, "I", "");
1283 
1284 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
1285     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1286     NULL, 0, sysctl_progressmeter, "I", "");
1287 
1288 #endif /* defined(XNU_TARGET_OS_OSX) */
1289 
1290 
1291 
1292 static int
sysctl_consoleoptions(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1293 sysctl_consoleoptions
1294 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1295 {
1296 	int error, changed;
1297 	uint32_t new_value;
1298 
1299 	error = sysctl_io_number(req, vc_user_options.options, sizeof(uint32_t), &new_value, &changed);
1300 
1301 	if (changed) {
1302 		vc_user_options.options = new_value;
1303 	}
1304 
1305 	return error;
1306 }
1307 
1308 static SYSCTL_PROC(_kern, OID_AUTO, consoleoptions,
1309     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1310     NULL, 0, sysctl_consoleoptions, "I", "");
1311 
1312 
1313 static int
1314 sysctl_progressoptions SYSCTL_HANDLER_ARGS
1315 {
1316 	return sysctl_io_opaque(req, &vc_user_options, sizeof(vc_user_options), NULL);
1317 }
1318 
1319 static SYSCTL_PROC(_kern, OID_AUTO, progressoptions,
1320     CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1321     NULL, 0, sysctl_progressoptions, "S,vc_progress_user_options", "");
1322 
1323 
1324 static int
1325 sysctl_wakereason SYSCTL_HANDLER_ARGS
1326 {
1327 	char wr[sizeof(gWakeReasonString)];
1328 
1329 	wr[0] = '\0';
1330 	if (gRootDomain && gWakeReasonSysctlRegistered) {
1331 		gRootDomain->copyWakeReasonString(wr, sizeof(wr));
1332 	} else {
1333 		return ENOENT;
1334 	}
1335 
1336 	return sysctl_io_string(req, wr, 0, 0, NULL);
1337 }
1338 
1339 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
1340     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1341     NULL, 0, sysctl_wakereason, "A", "wakereason");
1342 
1343 static int
1344 sysctl_bootreason SYSCTL_HANDLER_ARGS
1345 {
1346 	if (!os_atomic_load(&gBootReasonSysctlRegistered, acquire)) {
1347 		return ENOENT;
1348 	}
1349 
1350 	return sysctl_io_string(req, gBootReasonString, 0, 0, NULL);
1351 }
1352 
1353 SYSCTL_PROC(_kern, OID_AUTO, bootreason,
1354     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1355     NULL, 0, sysctl_bootreason, "A", "");
1356 
1357 static int
1358 sysctl_shutdownreason SYSCTL_HANDLER_ARGS
1359 {
1360 	char sr[sizeof(gShutdownReasonString)];
1361 
1362 	sr[0] = '\0';
1363 	if (gRootDomain && gShutdownReasonSysctlRegistered) {
1364 		gRootDomain->copyShutdownReasonString(sr, sizeof(sr));
1365 	} else {
1366 		return ENOENT;
1367 	}
1368 
1369 	return sysctl_io_string(req, sr, 0, 0, NULL);
1370 }
1371 
1372 SYSCTL_PROC(_kern, OID_AUTO, shutdownreason,
1373     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1374     NULL, 0, sysctl_shutdownreason, "A", "shutdownreason");
1375 
1376 // This value is meant to represent the last time the device shut down
1377 // in a unit of the PMU driver's choosing see rdar://138590268 for details
1378 static int
1379 sysctl_shutdowntime SYSCTL_HANDLER_ARGS
1380 {
1381 	uint64_t shutdownTime = 0;
1382 
1383 	if (gRootDomain && gShutdownReasonSysctlRegistered) {
1384 		gRootDomain->copyShutdownTime(&shutdownTime);
1385 	} else {
1386 		return ENOENT;
1387 	}
1388 
1389 	return SYSCTL_OUT(req, &shutdownTime, sizeof(shutdownTime));
1390 }
1391 
1392 SYSCTL_PROC(_kern, OID_AUTO, shutdowntime,
1393     CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1394     NULL, 0, sysctl_shutdowntime, "Q", "shutdowntime");
1395 
1396 static int
1397 sysctl_targettype SYSCTL_HANDLER_ARGS
1398 {
1399 	IOService * root;
1400 	OSSharedPtr<OSObject>  obj;
1401 	OSData *    data;
1402 	char        tt[32];
1403 
1404 	tt[0] = '\0';
1405 	root = IOService::getServiceRoot();
1406 	if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1407 		if ((data = OSDynamicCast(OSData, obj.get()))) {
1408 			strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1409 		}
1410 	}
1411 	return sysctl_io_string(req, tt, 0, 0, NULL);
1412 }
1413 
1414 SYSCTL_PROC(_hw, OID_AUTO, targettype,
1415     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1416     NULL, 0, sysctl_targettype, "A", "targettype");
1417 
1418 static SECURITY_READ_ONLY_LATE(char*) jetsam_properties_product_type_string = NULL;
1419 static SECURITY_READ_ONLY_LATE(size_t) jetsam_properties_product_type_string_len = 0;
1420 
1421 /*
1422  * SecureDTLookupEntry() is only guaranteed to work before PE_init_iokit(),
1423  * so we load the jetsam_properties_product_type string (if available) in a startup handler.
1424  */
1425 __startup_func
1426 static void
sysctl_load_jetsam_properties_product_type(void)1427 sysctl_load_jetsam_properties_product_type(void)
1428 {
1429 	DTEntry node;
1430 	void const *value = NULL;
1431 	unsigned int size = 0;
1432 
1433 	if (kSuccess != SecureDTLookupEntry(nullptr, "/product", &node)) {
1434 		return;
1435 	}
1436 
1437 	if (kSuccess != SecureDTGetProperty(node, "jetsam-properties-product-type", (void const **) &value, &size)) {
1438 		return;
1439 	}
1440 
1441 	if (size == 0) {
1442 		return;
1443 	}
1444 
1445 	jetsam_properties_product_type_string = (char *) zalloc_permanent(size, ZALIGN_NONE);
1446 	if (jetsam_properties_product_type_string == NULL) {
1447 		return;
1448 	}
1449 
1450 	memcpy(jetsam_properties_product_type_string, value, size);
1451 	jetsam_properties_product_type_string_len = size;
1452 }
1453 STARTUP(SYSCTL, STARTUP_RANK_MIDDLE, sysctl_load_jetsam_properties_product_type);
1454 
1455 static int
1456 sysctl_jetsam_properties_product_type SYSCTL_HANDLER_ARGS
1457 {
1458 	if (jetsam_properties_product_type_string != NULL) {
1459 		return SYSCTL_OUT(req, jetsam_properties_product_type_string, jetsam_properties_product_type_string_len);
1460 	}
1461 
1462 	IOService * root;
1463 	OSSharedPtr<OSObject>  obj;
1464 	OSData *    data;
1465 	char        tt[32];
1466 
1467 	tt[0] = '\0';
1468 	root = IOService::getServiceRoot();
1469 	if (root && (obj = root->copyProperty(gIODTTargetTypeKey))) {
1470 		if ((data = OSDynamicCast(OSData, obj.get()))) {
1471 			strlcpy(tt, (const char *) data->getBytesNoCopy(), sizeof(tt));
1472 		}
1473 	}
1474 	return sysctl_io_string(req, tt, 0, 0, NULL);
1475 }
1476 
1477 SYSCTL_PROC(_hw, OID_AUTO, jetsam_properties_product_type,
1478     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
1479     NULL, 0, sysctl_jetsam_properties_product_type, "A", "jetsam_properties_product_type");
1480 
1481 static SYSCTL_INT(_debug, OID_AUTO, noidle, CTLFLAG_RW, &gNoIdleFlag, 0, "");
1482 static SYSCTL_INT(_debug, OID_AUTO, swd_sleep_timeout, CTLFLAG_RW, &gSwdSleepTimeout, 0, "");
1483 static SYSCTL_INT(_debug, OID_AUTO, swd_wake_timeout, CTLFLAG_RW, &gSwdWakeTimeout, 0, "");
1484 static SYSCTL_INT(_debug, OID_AUTO, swd_timeout, CTLFLAG_RW, &gSwdSleepWakeTimeout, 0, "");
1485 static SYSCTL_INT(_debug, OID_AUTO, swd_panic, CTLFLAG_RW, &gSwdPanic, 0, "");
1486 #if DEVELOPMENT || DEBUG
1487 static SYSCTL_INT(_debug, OID_AUTO, swd_panic_phase, CTLFLAG_RW, &swd_panic_phase, 0, "");
1488 #if defined(XNU_TARGET_OS_OSX)
1489 static SYSCTL_INT(_debug, OID_AUTO, clamshell, CTLFLAG_RW, &gClamshellFlags, 0, "");
1490 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
1491 #endif /* defined(XNU_TARGET_OS_OSX) */
1492 #endif /* DEVELOPMENT || DEBUG */
1493 
1494 //******************************************************************************
1495 // AOT
1496 
1497 static int
1498 sysctl_aotmetrics SYSCTL_HANDLER_ARGS
1499 {
1500 	if (NULL == gRootDomain) {
1501 		return ENOENT;
1502 	}
1503 	if (NULL == gRootDomain->_aotMetrics) {
1504 		IOPMAOTMetrics nullMetrics = {};
1505 		return sysctl_io_opaque(req, &nullMetrics, sizeof(IOPMAOTMetrics), NULL);
1506 	}
1507 	return sysctl_io_opaque(req, gRootDomain->_aotMetrics, sizeof(IOPMAOTMetrics), NULL);
1508 }
1509 
1510 TUNABLE_DT_WRITEABLE(uint32_t, gAOTMode, "/product/iopm",
1511     "aot-mode", "aot_mode", 0, TUNABLE_DT_NONE);
1512 static SYSCTL_PROC(_kern, OID_AUTO, aotmetrics,
1513     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1514     NULL, 0, sysctl_aotmetrics, "S,IOPMAOTMetrics", "");
1515 
1516 
1517 static int
update_aotmode(uint32_t mode)1518 update_aotmode(uint32_t mode)
1519 {
1520 	int result;
1521 
1522 	if (!gIOPMWorkLoop) {
1523 		return ENOENT;
1524 	}
1525 	result = gIOPMWorkLoop->runActionBlock(^IOReturn (void) {
1526 		unsigned int oldCount;
1527 
1528 		if (mode && !gRootDomain->_aotMetrics) {
1529 		        gRootDomain->_aotMetrics = IOMallocType(IOPMAOTMetrics);
1530 		}
1531 
1532 		oldCount = gRootDomain->idleSleepPreventersCount();
1533 		gRootDomain->_aotMode = (mode & kIOPMAOTModeMask);
1534 		gRootDomain->updatePreventIdleSleepListInternal(NULL, false, oldCount);
1535 		return 0;
1536 	});
1537 	return result;
1538 }
1539 
1540 static int
sysctl_aotmodebits(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1541 sysctl_aotmodebits
1542 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1543 {
1544 	int error, changed;
1545 	uint32_t new_value;
1546 
1547 	if (NULL == gRootDomain) {
1548 		return ENOENT;
1549 	}
1550 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1551 	if (changed && gIOPMWorkLoop) {
1552 		error = update_aotmode(new_value);
1553 	}
1554 
1555 	return error;
1556 }
1557 
1558 static SYSCTL_PROC(_kern, OID_AUTO, aotmodebits,
1559     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1560     NULL, 0, sysctl_aotmodebits, "I", "");
1561 
1562 static int
sysctl_aotmode(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1563 sysctl_aotmode
1564 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1565 {
1566 	int error, changed;
1567 	uint32_t new_value;
1568 
1569 	if (NULL == gRootDomain) {
1570 		return ENOENT;
1571 	}
1572 	error = sysctl_io_number(req, gRootDomain->_aotMode, sizeof(uint32_t), &new_value, &changed);
1573 	if (changed && gIOPMWorkLoop) {
1574 		if (new_value) {
1575 			new_value = kIOPMAOTModeDefault; // & ~kIOPMAOTModeRespectTimers;
1576 		}
1577 		error = update_aotmode(new_value);
1578 	}
1579 
1580 	return error;
1581 }
1582 
1583 static SYSCTL_PROC(_kern, OID_AUTO, aotmode,
1584     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
1585     NULL, 0, sysctl_aotmode, "I", "");
1586 
1587 TUNABLE_DT(uint32_t, gAOTLingerTimeMS, "/product/iopm",
1588     "aot-linger-time-ms", "aot_linger_time_ms", 800, TUNABLE_DT_NONE);
1589 
1590 // Low Power Wake tunables
1591 TUNABLE_DT_WRITEABLE(uint64_t, gLPWFlags, "/product/iopm",
1592     "low-power-wake", "low_power_wake", false, TUNABLE_DT_NONE);
1593 static SYSCTL_QUAD(_kern, OID_AUTO, lowpowerwake, CTLFLAG_RW | CTLFLAG_LOCKED,
1594     &gLPWFlags, "Low Power Wake");
1595 
1596 //******************************************************************************
1597 
1598 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeCalendarKey;
1599 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoWakeSecondsKey;
1600 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerCalendarKey;
1601 static OSSharedPtr<const OSSymbol> gIOPMSettingAutoPowerSecondsKey;
1602 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugWakeRelativeKey;
1603 static OSSharedPtr<const OSSymbol> gIOPMSettingDebugPowerRelativeKey;
1604 static OSSharedPtr<const OSSymbol> gIOPMSettingMaintenanceWakeCalendarKey;
1605 static OSSharedPtr<const OSSymbol> gIOPMSettingSleepServiceWakeCalendarKey;
1606 static OSSharedPtr<const OSSymbol> gIOPMSettingSilentRunningKey;
1607 static OSSharedPtr<const OSSymbol> gIOPMUserTriggeredFullWakeKey;
1608 static OSSharedPtr<const OSSymbol> gIOPMUserIsActiveKey;
1609 static OSSharedPtr<const OSSymbol> gIOPMSettingLowLatencyAudioModeKey;
1610 
1611 //******************************************************************************
1612 // start
1613 //
1614 //******************************************************************************
1615 
1616 #define kRootDomainSettingsCount           20
1617 #define kRootDomainNoPublishSettingsCount  4
1618 
1619 bool
start(IOService * nub)1620 IOPMrootDomain::start( IOService * nub )
1621 {
1622 	OSSharedPtr<OSIterator>      psIterator;
1623 	OSSharedPtr<OSDictionary>    tmpDict;
1624 
1625 	super::start(nub);
1626 
1627 	gRootDomain = this;
1628 	gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
1629 	gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
1630 	gIOPMSettingAutoPowerCalendarKey = OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey);
1631 	gIOPMSettingAutoPowerSecondsKey = OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey);
1632 	gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
1633 	gIOPMSettingDebugPowerRelativeKey = OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey);
1634 	gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
1635 	gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
1636 	gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
1637 	gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
1638 	gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
1639 	gIOPMSettingLowLatencyAudioModeKey = OSSymbol::withCStringNoCopy(kIOPMSettingLowLatencyAudioModeKey);
1640 
1641 	gIOPMStatsResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
1642 	gIOPMStatsResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
1643 	gIOPMStatsResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
1644 	gIOPMStatsResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
1645 	gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
1646 
1647 	sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
1648 	sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
1649 	gIOPMWakeTypeUserKey = OSSymbol::withCStringNoCopy(kIOPMRootDomainWakeTypeUser);
1650 
1651 	OSSharedPtr<const OSSymbol> settingsArr[kRootDomainSettingsCount] =
1652 	{
1653 		OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
1654 		gIOPMSettingAutoWakeSecondsKey,
1655 		gIOPMSettingAutoPowerSecondsKey,
1656 		gIOPMSettingAutoWakeCalendarKey,
1657 		gIOPMSettingAutoPowerCalendarKey,
1658 		gIOPMSettingDebugWakeRelativeKey,
1659 		gIOPMSettingDebugPowerRelativeKey,
1660 		OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
1661 		OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
1662 		OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
1663 		OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
1664 		OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
1665 		OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
1666 		OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
1667 		OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
1668 		OSSymbol::withCString(kIOPMStateConsoleShutdown),
1669 		OSSymbol::withCString(kIOPMSettingProModeControl),
1670 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1671 		gIOPMSettingSilentRunningKey,
1672 		gIOPMSettingLowLatencyAudioModeKey,
1673 	};
1674 
1675 	OSSharedPtr<const OSSymbol> noPublishSettingsArr[kRootDomainNoPublishSettingsCount] =
1676 	{
1677 		OSSymbol::withCString(kIOPMSettingProModeControl),
1678 		OSSymbol::withCString(kIOPMSettingProModeDefer),
1679 		gIOPMSettingSilentRunningKey,
1680 		gIOPMSettingLowLatencyAudioModeKey,
1681 	};
1682 
1683 #if DEVELOPMENT || DEBUG
1684 #if defined(XNU_TARGET_OS_OSX)
1685 	PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
1686 	PE_parse_boot_argn("clamshell", &gClamshellFlags, sizeof(gClamshellFlags));
1687 #endif /* defined(XNU_TARGET_OS_OSX) */
1688 #endif /* DEVELOPMENT || DEBUG */
1689 
1690 	PE_parse_boot_argn("noidle", &gNoIdleFlag, sizeof(gNoIdleFlag));
1691 	PE_parse_boot_argn("swd_sleeptimeout", &gSwdSleepTimeout, sizeof(gSwdSleepTimeout));
1692 	PE_parse_boot_argn("swd_waketimeout", &gSwdWakeTimeout, sizeof(gSwdWakeTimeout));
1693 	PE_parse_boot_argn("swd_timeout", &gSwdSleepWakeTimeout, sizeof(gSwdSleepWakeTimeout));
1694 	PE_parse_boot_argn("haltmspanic", &gHaltTimeMaxPanic, sizeof(gHaltTimeMaxPanic));
1695 	PE_parse_boot_argn("haltmslog", &gHaltTimeMaxLog, sizeof(gHaltTimeMaxLog));
1696 
1697 	_aotMode = gAOTMode;
1698 	_aotLingerTime = gAOTLingerTimeMS;
1699 	_aotMetrics = _aotMode ? IOMallocType(IOPMAOTMetrics) : NULL;
1700 
1701 	// read noidle setting from Device Tree
1702 	if (PE_get_default("no-idle", &gNoIdleFlag, sizeof(gNoIdleFlag))) {
1703 		DLOG("Setting gNoIdleFlag to %u from device tree\n", gNoIdleFlag);
1704 	}
1705 
1706 	queue_init(&aggressivesQueue);
1707 	aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
1708 	aggressivesData = OSData::withCapacity(
1709 		sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
1710 
1711 	featuresDictLock = IOLockAlloc();
1712 	settingsCtrlLock = IOLockAlloc();
1713 	wakeEventLock = IOLockAlloc();
1714 	gHaltLogLock = IOLockAlloc();
1715 	setPMRootDomain(this);
1716 
1717 	extraSleepTimer = thread_call_allocate(
1718 		idleSleepTimerExpired,
1719 		(thread_call_param_t) this);
1720 
1721 	powerButtonDown = thread_call_allocate(
1722 		powerButtonDownCallout,
1723 		(thread_call_param_t) this);
1724 
1725 	powerButtonUp = thread_call_allocate(
1726 		powerButtonUpCallout,
1727 		(thread_call_param_t) this);
1728 
1729 	diskSyncCalloutEntry = thread_call_allocate(
1730 		&disk_sync_callout,
1731 		(thread_call_param_t) this);
1732 	updateConsoleUsersEntry = thread_call_allocate(
1733 		&updateConsoleUsersCallout,
1734 		(thread_call_param_t) this);
1735 
1736 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
1737 	fullWakeThreadCall = thread_call_allocate_with_options(
1738 		OSMemberFunctionCast(thread_call_func_t, this,
1739 		&IOPMrootDomain::fullWakeDelayedWork),
1740 		(thread_call_param_t) this, THREAD_CALL_PRIORITY_KERNEL,
1741 		THREAD_CALL_OPTIONS_ONCE);
1742 #endif
1743 
1744 	setProperty(kIOSleepSupportedKey, true);
1745 
1746 	bzero(&gPMStats, sizeof(gPMStats));
1747 
1748 	pmTracer = PMTraceWorker::tracer(this);
1749 
1750 	pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
1751 
1752 	userDisabledAllSleep = false;
1753 	systemBooting = true;
1754 	idleSleepEnabled = false;
1755 	idleSleepRevertible = true;
1756 	sleepSlider = 0;
1757 	idleSleepTimerPending = false;
1758 	wrangler = NULL;
1759 	clamshellClosed = false;
1760 	clamshellExists = false;
1761 #if DISPLAY_WRANGLER_PRESENT
1762 	clamshellDisabled = true;
1763 #else
1764 	clamshellDisabled = false;
1765 #endif
1766 	clamshellIgnoreClose = false;
1767 	acAdaptorConnected = true;
1768 	clamshellSleepDisableMask = 0;
1769 	gWakeReasonString[0] = '\0';
1770 
1771 	// Initialize to user active.
1772 	// Will never transition to user inactive w/o wrangler.
1773 	fullWakeReason = kFullWakeReasonLocalUser;
1774 	userIsActive = userWasActive = true;
1775 	clock_get_uptime(&gUserActiveAbsTime);
1776 	setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
1777 
1778 	// Set the default system capabilities at boot.
1779 	_currentCapability = kIOPMSystemCapabilityCPU      |
1780 	    kIOPMSystemCapabilityGraphics |
1781 	    kIOPMSystemCapabilityAudio    |
1782 	    kIOPMSystemCapabilityNetwork;
1783 
1784 	_pendingCapability = _currentCapability;
1785 	_desiredCapability = _currentCapability;
1786 	_highestCapability = _currentCapability;
1787 	setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
1788 
1789 	queuedSleepWakeUUIDString = NULL;
1790 	initializeBootSessionUUID();
1791 	pmStatsAppResponses     = OSArray::withCapacity(5);
1792 	_statsNameKey           = OSSymbol::withCString(kIOPMStatsNameKey);
1793 	_statsPIDKey            = OSSymbol::withCString(kIOPMStatsPIDKey);
1794 	_statsTimeMSKey         = OSSymbol::withCString(kIOPMStatsTimeMSKey);
1795 	_statsResponseTypeKey   = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
1796 	_statsMessageTypeKey    = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
1797 	_statsPowerCapsKey      = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
1798 	assertOnWakeSecs        = -1;// Invalid value to prevent updates
1799 
1800 	pmStatsLock = IOLockAlloc();
1801 	idxPMCPUClamshell = kCPUUnknownIndex;
1802 	idxPMCPULimitedPower = kCPUUnknownIndex;
1803 
1804 	tmpDict = OSDictionary::withCapacity(1);
1805 	setProperty(kRootDomainSupportedFeatures, tmpDict.get());
1806 
1807 	// Set a default "SystemPowerProfileOverrideDict" for platform
1808 	// drivers without any overrides.
1809 	if (!propertyExists(kIOPMSystemDefaultOverrideKey)) {
1810 		tmpDict = OSDictionary::withCapacity(1);
1811 		setProperty(kIOPMSystemDefaultOverrideKey, tmpDict.get());
1812 	}
1813 
1814 	settingsCallbacks = OSDictionary::withCapacity(1);
1815 
1816 	// Create a list of the valid PM settings that we'll relay to
1817 	// interested clients in setProperties() => setPMSetting()
1818 	allowedPMSettings = OSArray::withObjects(
1819 		(const OSObject **)settingsArr,
1820 		kRootDomainSettingsCount,
1821 		0);
1822 
1823 	// List of PM settings that should not automatically publish itself
1824 	// as a feature when registered by a listener.
1825 	noPublishPMSettings = OSArray::withObjects(
1826 		(const OSObject **)noPublishSettingsArr,
1827 		kRootDomainNoPublishSettingsCount,
1828 		0);
1829 
1830 	fPMSettingsDict = OSDictionary::withCapacity(5);
1831 	preventIdleSleepList = OSSet::withCapacity(8);
1832 	preventSystemSleepList = OSSet::withCapacity(2);
1833 
1834 	PMinit(); // creates gIOPMWorkLoop
1835 	gIOPMWorkLoop = getIOPMWorkloop();
1836 
1837 	commandGate = IOCommandGate::commandGate(gIOPMWorkLoop);
1838 	gIOPMWorkLoop->addEventSource(commandGate.get());
1839 
1840 	// Create IOPMPowerStateQueue used to queue external power
1841 	// events, and to handle those events on the PM work loop.
1842 	pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
1843 		this, OSMemberFunctionCast(IOEventSource::Action, this,
1844 		&IOPMrootDomain::dispatchPowerEvent));
1845 	gIOPMWorkLoop->addEventSource(pmPowerStateQueue);
1846 
1847 	_aotTimerES = IOTimerEventSource::timerEventSource(this,
1848 	    OSMemberFunctionCast(IOTimerEventSource::Action,
1849 	    this, &IOPMrootDomain::aotEvaluate));
1850 	gIOPMWorkLoop->addEventSource(_aotTimerES.get());
1851 
1852 	// Avoid publishing service early so gIOPMWorkLoop is
1853 	// guaranteed to be initialized by rootDomain.
1854 	publishPMRootDomain();
1855 
1856 	// create our power parent
1857 	gPatriarch = new IORootParent;
1858 	gPatriarch->init();
1859 	gPatriarch->attach(this);
1860 	gPatriarch->start(this);
1861 	gPatriarch->addPowerChild(this);
1862 
1863 	registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1864 	changePowerStateWithTagToPriv(ON_STATE, kCPSReasonInit);
1865 
1866 	// install power change handler
1867 	gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, NULL);
1868 
1869 #if DISPLAY_WRANGLER_PRESENT
1870 	wranglerIdleSettings = OSDictionary::withCapacity(1);
1871 	OSSharedPtr<OSNumber> wranglerIdlePeriod = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1872 
1873 	if (wranglerIdleSettings && wranglerIdlePeriod) {
1874 		wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1875 		    wranglerIdlePeriod.get());
1876 	}
1877 
1878 #endif /* DISPLAY_WRANGLER_PRESENT */
1879 
1880 	lowLatencyAudioNotifierDict       = OSDictionary::withCapacity(2);
1881 	lowLatencyAudioNotifyStateSym     = OSSymbol::withCString("LowLatencyAudioNotifyState");
1882 	lowLatencyAudioNotifyTimestampSym = OSSymbol::withCString("LowLatencyAudioNotifyTimestamp");
1883 	lowLatencyAudioNotifyStateVal     = OSNumber::withNumber(0ull, 32);
1884 	lowLatencyAudioNotifyTimestampVal = OSNumber::withNumber(0ull, 64);
1885 
1886 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
1887 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
1888 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyStateSym.get(), lowLatencyAudioNotifyStateVal.get());
1889 		lowLatencyAudioNotifierDict->setObject(lowLatencyAudioNotifyTimestampSym.get(), lowLatencyAudioNotifyTimestampVal.get());
1890 	}
1891 
1892 	OSSharedPtr<const OSSymbol> ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1893 	setProperty(gIOUserClientClassKey, const_cast<OSObject *>(static_cast<const OSObject *>(ucClassName.get())));
1894 
1895 	// IOBacklightDisplay can take a long time to load at boot, or it may
1896 	// not load at all if you're booting with clamshell closed. We publish
1897 	// 'DisplayDims' here redundantly to get it published early and at all.
1898 	OSSharedPtr<OSDictionary> matching;
1899 	matching = serviceMatching("IOPMPowerSource");
1900 	psIterator = getMatchingServices(matching.get());
1901 
1902 	if (psIterator && psIterator->getNextObject()) {
1903 		// There's at least one battery on the system, so we publish
1904 		// 'DisplayDims' support for the LCD.
1905 		publishFeature("DisplayDims");
1906 	}
1907 
1908 	// read swd_panic boot-arg
1909 	PE_parse_boot_argn("swd_panic", &gSwdPanic, sizeof(gSwdPanic));
1910 	gWillShutdownSysctlRegistered = true;
1911 
1912 #if HIBERNATION
1913 	IOHibernateSystemInit(this);
1914 #endif
1915 
1916 	registerService();                  // let clients find us
1917 
1918 	return true;
1919 }
1920 
1921 //******************************************************************************
1922 // setProperties
1923 //
1924 // Receive a setProperty call
1925 // The "System Boot" property means the system is completely booted.
1926 //******************************************************************************
1927 
1928 IOReturn
setProperties(OSObject * props_obj)1929 IOPMrootDomain::setProperties( OSObject * props_obj )
1930 {
1931 	IOReturn        return_value = kIOReturnSuccess;
1932 	OSDictionary    *dict = OSDynamicCast(OSDictionary, props_obj);
1933 	OSBoolean       *b = NULL;
1934 	OSNumber        *n = NULL;
1935 	const OSSymbol  *key = NULL;
1936 	OSObject        *obj = NULL;
1937 	OSSharedPtr<OSCollectionIterator> iter;
1938 
1939 	if (!dict) {
1940 		return kIOReturnBadArgument;
1941 	}
1942 
1943 	bool clientEntitled = false;
1944 	{
1945 		OSSharedPtr<OSObject> obj = IOUserClient::copyClientEntitlement(current_task(), kRootDomainEntitlementSetProperty);
1946 		clientEntitled = (obj == kOSBooleanTrue);
1947 	}
1948 
1949 	if (!clientEntitled) {
1950 		const char * errorSuffix = NULL;
1951 
1952 		// IOPMSchedulePowerEvent() clients may not be entitled, but must be root.
1953 		// That API can set 6 possible keys that are checked below.
1954 		if ((dict->getCount() == 1) &&
1955 		    (dict->getObject(gIOPMSettingAutoWakeSecondsKey.get()) ||
1956 		    dict->getObject(gIOPMSettingAutoPowerSecondsKey.get()) ||
1957 		    dict->getObject(gIOPMSettingAutoWakeCalendarKey.get()) ||
1958 		    dict->getObject(gIOPMSettingAutoPowerCalendarKey.get()) ||
1959 		    dict->getObject(gIOPMSettingDebugWakeRelativeKey.get()) ||
1960 		    dict->getObject(gIOPMSettingDebugPowerRelativeKey.get()))) {
1961 			return_value = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
1962 			if (return_value != kIOReturnSuccess) {
1963 				errorSuffix = "privileged";
1964 			}
1965 		} else {
1966 			return_value = kIOReturnNotPermitted;
1967 			errorSuffix = "entitled";
1968 		}
1969 
1970 		if (return_value != kIOReturnSuccess) {
1971 			OSSharedPtr<OSString> procName(IOCopyLogNameForPID(proc_selfpid()), OSNoRetain);
1972 			DLOG("%s failed, process %s is not %s\n", __func__,
1973 			    procName ? procName->getCStringNoCopy() : "", errorSuffix);
1974 			return return_value;
1975 		}
1976 	}
1977 
1978 	OSSharedPtr<const OSSymbol> publish_simulated_battery_string    = OSSymbol::withCString("SoftwareSimulatedBatteries");
1979 	OSSharedPtr<const OSSymbol> boot_complete_string                = OSSymbol::withCString("System Boot Complete");
1980 	OSSharedPtr<const OSSymbol> sys_shutdown_string                 = OSSymbol::withCString("System Shutdown");
1981 	OSSharedPtr<const OSSymbol> stall_halt_string                   = OSSymbol::withCString("StallSystemAtHalt");
1982 	OSSharedPtr<const OSSymbol> battery_warning_disabled_string     = OSSymbol::withCString("BatteryWarningsDisabled");
1983 	OSSharedPtr<const OSSymbol> idle_seconds_string                 = OSSymbol::withCString("System Idle Seconds");
1984 	OSSharedPtr<const OSSymbol> idle_milliseconds_string            = OSSymbol::withCString("System Idle Milliseconds");
1985 	OSSharedPtr<const OSSymbol> sleepdisabled_string                = OSSymbol::withCString("SleepDisabled");
1986 	OSSharedPtr<const OSSymbol> ondeck_sleepwake_uuid_string        = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1987 	OSSharedPtr<const OSSymbol> loginwindow_progress_string         = OSSymbol::withCString(kIOPMLoginWindowProgressKey);
1988 	OSSharedPtr<const OSSymbol> coredisplay_progress_string         = OSSymbol::withCString(kIOPMCoreDisplayProgressKey);
1989 	OSSharedPtr<const OSSymbol> coregraphics_progress_string        = OSSymbol::withCString(kIOPMCoreGraphicsProgressKey);
1990 #if DEBUG || DEVELOPMENT
1991 	OSSharedPtr<const OSSymbol> clamshell_close_string              = OSSymbol::withCString("IOPMTestClamshellClose");
1992 	OSSharedPtr<const OSSymbol> clamshell_open_string               = OSSymbol::withCString("IOPMTestClamshellOpen");
1993 	OSSharedPtr<const OSSymbol> ac_detach_string                    = OSSymbol::withCString("IOPMTestACDetach");
1994 	OSSharedPtr<const OSSymbol> ac_attach_string                    = OSSymbol::withCString("IOPMTestACAttach");
1995 	OSSharedPtr<const OSSymbol> desktopmode_set_string              = OSSymbol::withCString("IOPMTestDesktopModeSet");
1996 	OSSharedPtr<const OSSymbol> desktopmode_remove_string           = OSSymbol::withCString("IOPMTestDesktopModeRemove");
1997 #endif
1998 
1999 #if HIBERNATION
2000 	OSSharedPtr<const OSSymbol> hibernatemode_string                = OSSymbol::withCString(kIOHibernateModeKey);
2001 	OSSharedPtr<const OSSymbol> hibernatefile_string                = OSSymbol::withCString(kIOHibernateFileKey);
2002 	OSSharedPtr<const OSSymbol> hibernatefilemin_string             = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
2003 	OSSharedPtr<const OSSymbol> hibernatefilemax_string             = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
2004 	OSSharedPtr<const OSSymbol> hibernatefreeratio_string           = OSSymbol::withCString(kIOHibernateFreeRatioKey);
2005 	OSSharedPtr<const OSSymbol> hibernatefreetime_string            = OSSymbol::withCString(kIOHibernateFreeTimeKey);
2006 #endif
2007 
2008 	iter = OSCollectionIterator::withCollection(dict);
2009 	if (!iter) {
2010 		return_value = kIOReturnNoMemory;
2011 		goto exit;
2012 	}
2013 
2014 	while ((key = (const OSSymbol *) iter->getNextObject()) &&
2015 	    (obj = dict->getObject(key))) {
2016 		if (key->isEqualTo(publish_simulated_battery_string.get())) {
2017 			if (OSDynamicCast(OSBoolean, obj)) {
2018 				publishResource(key, kOSBooleanTrue);
2019 			}
2020 		} else if (key->isEqualTo(idle_seconds_string.get())) {
2021 			if ((n = OSDynamicCast(OSNumber, obj))) {
2022 				setProperty(key, n);
2023 				idleMilliSeconds = n->unsigned32BitValue() * 1000;
2024 			}
2025 		} else if (key->isEqualTo(idle_milliseconds_string.get())) {
2026 			if ((n = OSDynamicCast(OSNumber, obj))) {
2027 				setProperty(key, n);
2028 				idleMilliSeconds = n->unsigned32BitValue();
2029 			}
2030 		} else if (key->isEqualTo(boot_complete_string.get())) {
2031 			pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
2032 		} else if (key->isEqualTo(sys_shutdown_string.get())) {
2033 			if ((b = OSDynamicCast(OSBoolean, obj))) {
2034 				pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
2035 			}
2036 		} else if (key->isEqualTo(battery_warning_disabled_string.get())) {
2037 			setProperty(key, obj);
2038 		}
2039 #if HIBERNATION
2040 		else if (key->isEqualTo(hibernatemode_string.get()) ||
2041 		    key->isEqualTo(hibernatefilemin_string.get()) ||
2042 		    key->isEqualTo(hibernatefilemax_string.get()) ||
2043 		    key->isEqualTo(hibernatefreeratio_string.get()) ||
2044 		    key->isEqualTo(hibernatefreetime_string.get())) {
2045 			if ((n = OSDynamicCast(OSNumber, obj))) {
2046 				setProperty(key, n);
2047 			}
2048 		} else if (key->isEqualTo(hibernatefile_string.get())) {
2049 			OSString * str = OSDynamicCast(OSString, obj);
2050 			if (str) {
2051 				setProperty(key, str);
2052 			}
2053 		}
2054 #endif
2055 		else if (key->isEqualTo(sleepdisabled_string.get())) {
2056 			if ((b = OSDynamicCast(OSBoolean, obj))) {
2057 				setProperty(key, b);
2058 				pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
2059 			}
2060 		} else if (key->isEqualTo(ondeck_sleepwake_uuid_string.get())) {
2061 			obj->retain();
2062 			pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
2063 		} else if (key->isEqualTo(loginwindow_progress_string.get())) {
2064 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2065 				uint32_t data = n->unsigned32BitValue();
2066 				pmTracer->traceComponentWakeProgress(kIOPMLoginWindowProgress, data);
2067 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMLoginWindowProgress, data);
2068 			}
2069 		} else if (key->isEqualTo(coredisplay_progress_string.get())) {
2070 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2071 				uint32_t data = n->unsigned32BitValue();
2072 				pmTracer->traceComponentWakeProgress(kIOPMCoreDisplayProgress, data);
2073 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreDisplayProgress, data);
2074 			}
2075 		} else if (key->isEqualTo(coregraphics_progress_string.get())) {
2076 			if (pmTracer && (n = OSDynamicCast(OSNumber, obj))) {
2077 				uint32_t data = n->unsigned32BitValue();
2078 				pmTracer->traceComponentWakeProgress(kIOPMCoreGraphicsProgress, data);
2079 				kdebugTrace(kPMLogComponentWakeProgress, 0, kIOPMCoreGraphicsProgress, data);
2080 			}
2081 		} else if (key->isEqualTo(kIOPMDeepSleepEnabledKey) ||
2082 		    key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey) ||
2083 		    key->isEqualTo(kIOPMAutoPowerOffEnabledKey) ||
2084 		    key->isEqualTo(stall_halt_string.get())) {
2085 			if ((b = OSDynamicCast(OSBoolean, obj))) {
2086 				setProperty(key, b);
2087 			}
2088 		} else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
2089 		    key->isEqualTo(kIOPMDeepSleepTimerKey) ||
2090 		    key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
2091 		    key->isEqualTo(kIOPMAutoPowerOffTimerKey)) {
2092 			if ((n = OSDynamicCast(OSNumber, obj))) {
2093 				setProperty(key, n);
2094 			}
2095 		} else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) {
2096 			if (kOSBooleanTrue == obj) {
2097 				OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2098 			} else {
2099 				OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarmMask);
2100 			}
2101 			DLOG("_userScheduledAlarmMask 0x%x\n", (uint32_t) _userScheduledAlarmMask);
2102 		}
2103 #if DEBUG || DEVELOPMENT
2104 		else if (key->isEqualTo(clamshell_close_string.get())) {
2105 			DLOG("SetProperties: setting clamshell close\n");
2106 			UInt32 msg = kIOPMClamshellClosed;
2107 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2108 		} else if (key->isEqualTo(clamshell_open_string.get())) {
2109 			DLOG("SetProperties: setting clamshell open\n");
2110 			UInt32 msg = kIOPMClamshellOpened;
2111 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2112 		} else if (key->isEqualTo(ac_detach_string.get())) {
2113 			DLOG("SetProperties: setting ac detach\n");
2114 			UInt32 msg = kIOPMSetACAdaptorConnected;
2115 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2116 		} else if (key->isEqualTo(ac_attach_string.get())) {
2117 			DLOG("SetProperties: setting ac attach\n");
2118 			UInt32 msg = kIOPMSetACAdaptorConnected | kIOPMSetValue;
2119 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2120 		} else if (key->isEqualTo(desktopmode_set_string.get())) {
2121 			DLOG("SetProperties: setting desktopmode");
2122 			UInt32 msg = kIOPMSetDesktopMode | kIOPMSetValue;
2123 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2124 		} else if (key->isEqualTo(desktopmode_remove_string.get())) {
2125 			DLOG("SetProperties: removing desktopmode\n");
2126 			UInt32 msg = kIOPMSetDesktopMode;
2127 			pmPowerStateQueue->submitPowerEvent(kPowerEventReceivedPowerNotification, (void *)(uintptr_t)msg);
2128 		}
2129 #endif
2130 		// Relay our allowed PM settings onto our registered PM clients
2131 		else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1)) {
2132 			return_value = setPMSetting(key, obj);
2133 			if (kIOReturnSuccess != return_value) {
2134 				break;
2135 			}
2136 		} else {
2137 			DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
2138 		}
2139 	}
2140 
2141 exit:
2142 	return return_value;
2143 }
2144 
2145 #if HIBERNATION
2146 // MARK: -
2147 // MARK: setLockdownModeHibernation
2148 // ***************************************************************************
2149 void
setLockdownModeHibernation(uint32_t status)2150 IOPMrootDomain::setLockdownModeHibernation(uint32_t status)
2151 {
2152 	if (!gIOPMWorkLoop->inGate()) {
2153 		gIOPMWorkLoop->runAction(
2154 			OSMemberFunctionCast(IOWorkLoop::Action, this,
2155 			&IOPMrootDomain::setLockdownModeHibernation),
2156 			this, (void *)(uintptr_t) status);
2157 		return;
2158 	}
2159 
2160 	ldmHibernateDisable = status;
2161 	DLOG("ldmHibernateDisable %d\n", status);
2162 	setProperty("IOPMLDMHibernationDisable", status);
2163 }
2164 #endif
2165 
2166 // MARK: -
2167 // MARK: Aggressiveness
2168 
2169 //******************************************************************************
2170 // setAggressiveness
2171 //
2172 // Override IOService::setAggressiveness()
2173 //******************************************************************************
2174 
2175 IOReturn
setAggressiveness(unsigned long type,unsigned long value)2176 IOPMrootDomain::setAggressiveness(
2177 	unsigned long   type,
2178 	unsigned long   value )
2179 {
2180 	return setAggressiveness( type, value, 0 );
2181 }
2182 
2183 /*
2184  * Private setAggressiveness() with an internal options argument.
2185  */
2186 IOReturn
setAggressiveness(unsigned long type,unsigned long value,IOOptionBits options)2187 IOPMrootDomain::setAggressiveness(
2188 	unsigned long   type,
2189 	unsigned long   value,
2190 	IOOptionBits    options )
2191 {
2192 	AggressivesRequest *    entry;
2193 	AggressivesRequest *    request;
2194 	bool                    found = false;
2195 
2196 	if ((type > UINT_MAX) || (value > UINT_MAX)) {
2197 		return kIOReturnBadArgument;
2198 	}
2199 
2200 	if (type == kPMMinutesToDim || type == kPMMinutesToSleep) {
2201 		DLOG("setAggressiveness(%x) %s = %u\n",
2202 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2203 	} else {
2204 		DEBUG_LOG("setAggressiveness(%x) %s = %u\n",
2205 		    (uint32_t) options, getAggressivenessTypeString((uint32_t) type), (uint32_t) value);
2206 	}
2207 
2208 	request = IOMallocType(AggressivesRequest);
2209 	request->options  = options;
2210 	request->dataType = kAggressivesRequestTypeRecord;
2211 	request->data.record.type  = (uint32_t) type;
2212 	request->data.record.value = (uint32_t) value;
2213 
2214 	AGGRESSIVES_LOCK();
2215 
2216 	// Update disk quick spindown flag used by getAggressiveness().
2217 	// Never merge requests with quick spindown flags set.
2218 
2219 	if (options & kAggressivesOptionQuickSpindownEnable) {
2220 		gAggressivesState |= kAggressivesStateQuickSpindown;
2221 	} else if (options & kAggressivesOptionQuickSpindownDisable) {
2222 		gAggressivesState &= ~kAggressivesStateQuickSpindown;
2223 	} else {
2224 		// Coalesce requests with identical aggressives types.
2225 		// Deal with callers that calls us too "aggressively".
2226 
2227 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2228 		{
2229 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2230 			    (entry->data.record.type == type) &&
2231 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2232 				entry->data.record.value = (uint32_t) value;
2233 				found = true;
2234 				break;
2235 			}
2236 		}
2237 	}
2238 
2239 	if (!found) {
2240 		queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2241 	}
2242 
2243 	AGGRESSIVES_UNLOCK();
2244 
2245 	if (found) {
2246 		IOFreeType(request, AggressivesRequest);
2247 	}
2248 
2249 	if (options & kAggressivesOptionSynchronous) {
2250 		handleAggressivesRequests(); // not truly synchronous
2251 	} else {
2252 		thread_call_enter(aggressivesThreadCall);
2253 	}
2254 
2255 	return kIOReturnSuccess;
2256 }
2257 
2258 //******************************************************************************
2259 // getAggressiveness
2260 //
2261 // Override IOService::setAggressiveness()
2262 // Fetch the aggressiveness factor with the given type.
2263 //******************************************************************************
2264 
2265 IOReturn
getAggressiveness(unsigned long type,unsigned long * outLevel)2266 IOPMrootDomain::getAggressiveness(
2267 	unsigned long   type,
2268 	unsigned long * outLevel )
2269 {
2270 	uint32_t    value  = 0;
2271 	int         source = 0;
2272 
2273 	if (!outLevel || (type > UINT_MAX)) {
2274 		return kIOReturnBadArgument;
2275 	}
2276 
2277 	AGGRESSIVES_LOCK();
2278 
2279 	// Disk quick spindown in effect, report value = 1
2280 
2281 	if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
2282 	    (type == kPMMinutesToSpinDown)) {
2283 		value  = kAggressivesMinValue;
2284 		source = 1;
2285 	}
2286 
2287 	// Consult the pending request queue.
2288 
2289 	if (!source) {
2290 		AggressivesRequest * entry;
2291 
2292 		queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
2293 		{
2294 			if ((entry->dataType == kAggressivesRequestTypeRecord) &&
2295 			    (entry->data.record.type == type) &&
2296 			    ((entry->options & kAggressivesOptionQuickSpindownMask) == 0)) {
2297 				value  = entry->data.record.value;
2298 				source = 2;
2299 				break;
2300 			}
2301 		}
2302 	}
2303 
2304 	// Consult the backend records.
2305 
2306 	if (!source && aggressivesData) {
2307 		AggressivesRecord * record;
2308 		int                 i, count;
2309 
2310 		count  = aggressivesData->getLength() / sizeof(AggressivesRecord);
2311 		record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2312 
2313 		for (i = 0; i < count; i++, record++) {
2314 			if (record->type == type) {
2315 				value  = record->value;
2316 				source = 3;
2317 				break;
2318 			}
2319 		}
2320 	}
2321 
2322 	AGGRESSIVES_UNLOCK();
2323 
2324 	if (source) {
2325 		*outLevel = (unsigned long) value;
2326 		return kIOReturnSuccess;
2327 	} else {
2328 		DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
2329 		*outLevel = 0; // default return = 0, driver may not check for error
2330 		return kIOReturnInvalid;
2331 	}
2332 }
2333 
2334 //******************************************************************************
2335 // joinAggressiveness
2336 //
2337 // Request from IOService to join future aggressiveness broadcasts.
2338 //******************************************************************************
2339 
2340 IOReturn
joinAggressiveness(IOService * service)2341 IOPMrootDomain::joinAggressiveness(
2342 	IOService * service )
2343 {
2344 	AggressivesRequest *    request;
2345 
2346 	if (!service || (service == this)) {
2347 		return kIOReturnBadArgument;
2348 	}
2349 
2350 	DEBUG_LOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
2351 
2352 	request = IOMallocType(AggressivesRequest);
2353 	request->dataType = kAggressivesRequestTypeService;
2354 	request->data.service.reset(service, OSRetain); // released by synchronizeAggressives()
2355 
2356 	AGGRESSIVES_LOCK();
2357 	queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
2358 	AGGRESSIVES_UNLOCK();
2359 
2360 	thread_call_enter(aggressivesThreadCall);
2361 
2362 	return kIOReturnSuccess;
2363 }
2364 
2365 //******************************************************************************
2366 // handleAggressivesRequests
2367 //
2368 // Backend thread processes all incoming aggressiveness requests in the queue.
2369 //******************************************************************************
2370 
2371 static void
handleAggressivesFunction(thread_call_param_t param1,thread_call_param_t param2)2372 handleAggressivesFunction(
2373 	thread_call_param_t param1,
2374 	thread_call_param_t param2 )
2375 {
2376 	if (param1) {
2377 		((IOPMrootDomain *) param1)->handleAggressivesRequests();
2378 	}
2379 }
2380 
2381 void
handleAggressivesRequests(void)2382 IOPMrootDomain::handleAggressivesRequests( void )
2383 {
2384 	AggressivesRecord *     start;
2385 	AggressivesRecord *     record;
2386 	AggressivesRequest *    request;
2387 	queue_head_t            joinedQueue;
2388 	int                     i, count;
2389 	bool                    broadcast;
2390 	bool                    found;
2391 	bool                    pingSelf = false;
2392 
2393 	AGGRESSIVES_LOCK();
2394 
2395 	if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
2396 	    queue_empty(&aggressivesQueue)) {
2397 		goto unlock_done;
2398 	}
2399 
2400 	gAggressivesState |= kAggressivesStateBusy;
2401 	count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2402 	start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2403 
2404 	do{
2405 		broadcast = false;
2406 		queue_init(&joinedQueue);
2407 
2408 		do{
2409 			// Remove request from the incoming queue in FIFO order.
2410 			queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
2411 			switch (request->dataType) {
2412 			case kAggressivesRequestTypeRecord:
2413 				// Update existing record if found.
2414 				found = false;
2415 				for (i = 0, record = start; i < count; i++, record++) {
2416 					if (record->type == request->data.record.type) {
2417 						found = true;
2418 
2419 						if (request->options & kAggressivesOptionQuickSpindownEnable) {
2420 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2421 								broadcast = true;
2422 								record->flags |= (kAggressivesRecordFlagMinValue |
2423 								    kAggressivesRecordFlagModified);
2424 								DLOG("disk spindown accelerated, was %u min\n",
2425 								    record->value);
2426 							}
2427 						} else if (request->options & kAggressivesOptionQuickSpindownDisable) {
2428 							if (record->flags & kAggressivesRecordFlagMinValue) {
2429 								broadcast = true;
2430 								record->flags |= kAggressivesRecordFlagModified;
2431 								record->flags &= ~kAggressivesRecordFlagMinValue;
2432 								DLOG("disk spindown restored to %u min\n",
2433 								    record->value);
2434 							}
2435 						} else if (record->value != request->data.record.value) {
2436 							record->value = request->data.record.value;
2437 							if ((record->flags & kAggressivesRecordFlagMinValue) == 0) {
2438 								broadcast = true;
2439 								record->flags |= kAggressivesRecordFlagModified;
2440 							}
2441 						}
2442 						break;
2443 					}
2444 				}
2445 
2446 				// No matching record, append a new record.
2447 				if (!found &&
2448 				    ((request->options & kAggressivesOptionQuickSpindownDisable) == 0)) {
2449 					AggressivesRecord   newRecord;
2450 
2451 					newRecord.flags = kAggressivesRecordFlagModified;
2452 					newRecord.type  = request->data.record.type;
2453 					newRecord.value = request->data.record.value;
2454 					if (request->options & kAggressivesOptionQuickSpindownEnable) {
2455 						newRecord.flags |= kAggressivesRecordFlagMinValue;
2456 						DLOG("disk spindown accelerated\n");
2457 					}
2458 
2459 					aggressivesData->appendValue(newRecord);
2460 
2461 					// OSData may have switched to another (larger) buffer.
2462 					count = aggressivesData->getLength() / sizeof(AggressivesRecord);
2463 					start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
2464 					broadcast = true;
2465 				}
2466 
2467 				// Finished processing the request, release it.
2468 				IOFreeType(request, AggressivesRequest);
2469 				break;
2470 
2471 			case kAggressivesRequestTypeService:
2472 				// synchronizeAggressives() will free request.
2473 				queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
2474 				break;
2475 
2476 			default:
2477 				panic("bad aggressives request type %x", request->dataType);
2478 				break;
2479 			}
2480 		} while (!queue_empty(&aggressivesQueue));
2481 
2482 		// Release the lock to perform work, with busy flag set.
2483 		if (!queue_empty(&joinedQueue) || broadcast) {
2484 			AGGRESSIVES_UNLOCK();
2485 			if (!queue_empty(&joinedQueue)) {
2486 				synchronizeAggressives(&joinedQueue, start, count);
2487 			}
2488 			if (broadcast) {
2489 				broadcastAggressives(start, count);
2490 			}
2491 			AGGRESSIVES_LOCK();
2492 		}
2493 
2494 		// Remove the modified flag from all records.
2495 		for (i = 0, record = start; i < count; i++, record++) {
2496 			if ((record->flags & kAggressivesRecordFlagModified) &&
2497 			    ((record->type == kPMMinutesToDim) ||
2498 			    (record->type == kPMMinutesToSleep))) {
2499 				pingSelf = true;
2500 			}
2501 
2502 			record->flags &= ~kAggressivesRecordFlagModified;
2503 		}
2504 
2505 		// Check the incoming queue again since new entries may have been
2506 		// added while lock was released above.
2507 	} while (!queue_empty(&aggressivesQueue));
2508 
2509 	gAggressivesState &= ~kAggressivesStateBusy;
2510 
2511 unlock_done:
2512 	AGGRESSIVES_UNLOCK();
2513 
2514 	// Root domain is interested in system and display sleep slider changes.
2515 	// Submit a power event to handle those changes on the PM work loop.
2516 
2517 	if (pingSelf && pmPowerStateQueue) {
2518 		pmPowerStateQueue->submitPowerEvent(
2519 			kPowerEventPolicyStimulus,
2520 			(void *) kStimulusAggressivenessChanged );
2521 	}
2522 }
2523 
2524 //******************************************************************************
2525 // synchronizeAggressives
2526 //
2527 // Push all known aggressiveness records to one or more IOService.
2528 //******************************************************************************
2529 
2530 void
synchronizeAggressives(queue_head_t * joinedQueue,const AggressivesRecord * array,int count)2531 IOPMrootDomain::synchronizeAggressives(
2532 	queue_head_t *              joinedQueue,
2533 	const AggressivesRecord *   array,
2534 	int                         count )
2535 {
2536 	OSSharedPtr<IOService>      service;
2537 	AggressivesRequest *        request;
2538 	const AggressivesRecord *   record;
2539 	IOPMDriverCallEntry         callEntry;
2540 	uint32_t                    value;
2541 	int                         i;
2542 
2543 	while (!queue_empty(joinedQueue)) {
2544 		queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
2545 		if (request->dataType == kAggressivesRequestTypeService) {
2546 			// retained by joinAggressiveness(), so take ownership
2547 			service = os::move(request->data.service);
2548 		} else {
2549 			service.reset();
2550 		}
2551 
2552 		IOFreeType(request, AggressivesRequest);
2553 		request = NULL;
2554 
2555 		if (service) {
2556 			if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2557 				for (i = 0, record = array; i < count; i++, record++) {
2558 					value = record->value;
2559 					if (record->flags & kAggressivesRecordFlagMinValue) {
2560 						value = kAggressivesMinValue;
2561 					}
2562 
2563 					_LOG("synchronizeAggressives 0x%x = %u to %s\n",
2564 					    record->type, value, service->getName());
2565 					service->setAggressiveness(record->type, value);
2566 				}
2567 				service->deassertPMDriverCall(&callEntry);
2568 			}
2569 		}
2570 	}
2571 }
2572 
2573 //******************************************************************************
2574 // broadcastAggressives
2575 //
2576 // Traverse PM tree and call setAggressiveness() for records that have changed.
2577 //******************************************************************************
2578 
2579 void
broadcastAggressives(const AggressivesRecord * array,int count)2580 IOPMrootDomain::broadcastAggressives(
2581 	const AggressivesRecord *   array,
2582 	int                         count )
2583 {
2584 	OSSharedPtr<IORegistryIterator> iter;
2585 	IORegistryEntry                *entry;
2586 	OSSharedPtr<IORegistryEntry>    child;
2587 	IOPowerConnection              *connect;
2588 	IOService                      *service;
2589 	const AggressivesRecord        *record;
2590 	IOPMDriverCallEntry             callEntry;
2591 	uint32_t                        value;
2592 	int                             i;
2593 
2594 	iter = IORegistryIterator::iterateOver(
2595 		this, gIOPowerPlane, kIORegistryIterateRecursively);
2596 	if (iter) {
2597 		do{
2598 			// !! reset the iterator
2599 			iter->reset();
2600 			while ((entry = iter->getNextObject())) {
2601 				connect = OSDynamicCast(IOPowerConnection, entry);
2602 				if (!connect || !connect->getReadyFlag()) {
2603 					continue;
2604 				}
2605 
2606 				child = connect->copyChildEntry(gIOPowerPlane);
2607 				if (child) {
2608 					if ((service = OSDynamicCast(IOService, child.get()))) {
2609 						if (service->assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetAggressive)) {
2610 							for (i = 0, record = array; i < count; i++, record++) {
2611 								if (record->flags & kAggressivesRecordFlagModified) {
2612 									value = record->value;
2613 									if (record->flags & kAggressivesRecordFlagMinValue) {
2614 										value = kAggressivesMinValue;
2615 									}
2616 									_LOG("broadcastAggressives %x = %u to %s\n",
2617 									    record->type, value, service->getName());
2618 									service->setAggressiveness(record->type, value);
2619 								}
2620 							}
2621 							service->deassertPMDriverCall(&callEntry);
2622 						}
2623 					}
2624 				}
2625 			}
2626 		}while (!entry && !iter->isValid());
2627 	}
2628 }
2629 
2630 //*****************************************
2631 // stackshot on power button press
2632 // ***************************************
2633 static void
powerButtonDownCallout(thread_call_param_t us,thread_call_param_t)2634 powerButtonDownCallout(thread_call_param_t us, thread_call_param_t )
2635 {
2636 	/* Power button pressed during wake
2637 	 * Take a stackshot
2638 	 */
2639 	DEBUG_LOG("Powerbutton: down. Taking stackshot\n");
2640 	((IOPMrootDomain *)us)->takeStackshot(false);
2641 }
2642 
2643 static void
powerButtonUpCallout(thread_call_param_t us,thread_call_param_t)2644 powerButtonUpCallout(thread_call_param_t us, thread_call_param_t)
2645 {
2646 	/* Power button released.
2647 	 * Delete any stackshot data
2648 	 */
2649 	DEBUG_LOG("PowerButton: up callout. Delete stackshot\n");
2650 	((IOPMrootDomain *)us)->deleteStackshot();
2651 }
2652 //*************************************************************************
2653 //
2654 
2655 // MARK: -
2656 // MARK: System Sleep
2657 
2658 //******************************************************************************
2659 // startIdleSleepTimer
2660 //
2661 //******************************************************************************
2662 
2663 void
startIdleSleepTimer(uint32_t inMilliSeconds)2664 IOPMrootDomain::startIdleSleepTimer( uint32_t inMilliSeconds )
2665 {
2666 	AbsoluteTime deadline;
2667 
2668 	ASSERT_GATED();
2669 	if (gNoIdleFlag) {
2670 		DLOG("idle timer not set (noidle=%d)\n", gNoIdleFlag);
2671 		return;
2672 	}
2673 	if (inMilliSeconds) {
2674 		if (inMilliSeconds < kMinimumTimeBeforeIdleSleep) {
2675 			AbsoluteTime    now;
2676 			uint64_t        nsec_since_wake;
2677 			uint64_t                msec_since_wake;
2678 
2679 			// Adjust idle timer so it will not expire until atleast kMinimumTimeBeforeIdleSleep milliseconds
2680 			// after the most recent AP wake.
2681 			clock_get_uptime(&now);
2682 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2683 			absolutetime_to_nanoseconds(now, &nsec_since_wake);
2684 			msec_since_wake = nsec_since_wake / NSEC_PER_MSEC;
2685 
2686 			if (msec_since_wake < kMinimumTimeBeforeIdleSleep) {
2687 				uint32_t newIdleTimer = kMinimumTimeBeforeIdleSleep - (uint32_t)msec_since_wake;
2688 
2689 				// Ensure that our new idle timer is not less than inMilliSeconds,
2690 				// as we should only be increasing the timer duration, not decreasing it
2691 				if (newIdleTimer > inMilliSeconds) {
2692 					DLOG("startIdleSleepTimer increasing timeout from %u to %u\n", inMilliSeconds, newIdleTimer);
2693 					inMilliSeconds = newIdleTimer;
2694 				}
2695 			}
2696 		}
2697 		clock_interval_to_deadline(inMilliSeconds, kMillisecondScale, &deadline);
2698 		thread_call_enter_delayed(extraSleepTimer, deadline);
2699 		idleSleepTimerPending = true;
2700 	} else {
2701 		thread_call_enter(extraSleepTimer);
2702 	}
2703 	DLOG("idle timer set for %u milliseconds\n", inMilliSeconds);
2704 }
2705 
2706 //******************************************************************************
2707 // cancelIdleSleepTimer
2708 //
2709 //******************************************************************************
2710 
2711 void
cancelIdleSleepTimer(void)2712 IOPMrootDomain::cancelIdleSleepTimer( void )
2713 {
2714 	ASSERT_GATED();
2715 	if (idleSleepTimerPending) {
2716 		DLOG("idle timer cancelled\n");
2717 		thread_call_cancel(extraSleepTimer);
2718 		idleSleepTimerPending = false;
2719 
2720 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
2721 			AbsoluteTime    now;
2722 			clock_usec_t    microsecs;
2723 			clock_get_uptime(&now);
2724 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
2725 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
2726 			if (assertOnWakeReport) {
2727 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
2728 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
2729 			}
2730 		}
2731 	}
2732 }
2733 
2734 //******************************************************************************
2735 // idleSleepTimerExpired
2736 //
2737 //******************************************************************************
2738 
2739 static void
idleSleepTimerExpired(thread_call_param_t us,thread_call_param_t)2740 idleSleepTimerExpired(
2741 	thread_call_param_t us, thread_call_param_t )
2742 {
2743 	((IOPMrootDomain *)us)->handleSleepTimerExpiration();
2744 }
2745 
2746 //******************************************************************************
2747 // handleSleepTimerExpiration
2748 //
2749 // The time between the sleep idle timeout and the next longest one has elapsed.
2750 // It's time to sleep. Start that by removing the clamp that's holding us awake.
2751 //******************************************************************************
2752 
2753 void
handleSleepTimerExpiration(void)2754 IOPMrootDomain::handleSleepTimerExpiration( void )
2755 {
2756 	if (!gIOPMWorkLoop->inGate()) {
2757 		gIOPMWorkLoop->runAction(
2758 			OSMemberFunctionCast(IOWorkLoop::Action, this,
2759 			&IOPMrootDomain::handleSleepTimerExpiration),
2760 			this);
2761 		return;
2762 	}
2763 
2764 	DLOG("sleep timer expired\n");
2765 	ASSERT_GATED();
2766 
2767 	idleSleepTimerPending = false;
2768 	setQuickSpinDownTimeout();
2769 	adjustPowerState(true);
2770 }
2771 
2772 //******************************************************************************
2773 // getTimeToIdleSleep
2774 //
2775 // Returns number of milliseconds left before going into idle sleep.
2776 // Caller has to make sure that idle sleep is allowed at the time of calling
2777 // this function
2778 //******************************************************************************
2779 
2780 uint32_t
getTimeToIdleSleep(void)2781 IOPMrootDomain::getTimeToIdleSleep( void )
2782 {
2783 	AbsoluteTime    now, lastActivityTime;
2784 	uint64_t        nanos;
2785 	uint32_t        minutesSinceUserInactive = 0;
2786 	uint32_t        sleepDelay = 0;
2787 
2788 	if (!idleSleepEnabled) {
2789 		return 0xffffffff;
2790 	}
2791 
2792 	if (userActivityTime) {
2793 		lastActivityTime = userActivityTime;
2794 	} else {
2795 		lastActivityTime = userBecameInactiveTime;
2796 	}
2797 
2798 	// Ignore any lastActivityTime that predates the last system wake.
2799 	// The goal is to avoid a sudden idle sleep right after a dark wake
2800 	// due to sleepDelay=0 computed below. The alternative 60s minimum
2801 	// timeout should be large enough to allow dark wake to complete,
2802 	// at which point the idle timer will be promptly cancelled.
2803 	clock_get_uptime(&now);
2804 	if ((CMP_ABSOLUTETIME(&lastActivityTime, &gIOLastWakeAbsTime) >= 0) &&
2805 	    (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)) {
2806 		SUB_ABSOLUTETIME(&now, &lastActivityTime);
2807 		absolutetime_to_nanoseconds(now, &nanos);
2808 		minutesSinceUserInactive = nanos / (60000000000ULL);
2809 
2810 		if (minutesSinceUserInactive >= sleepSlider) {
2811 			sleepDelay = 0;
2812 		} else {
2813 			sleepDelay = sleepSlider - minutesSinceUserInactive;
2814 		}
2815 	} else {
2816 		DLOG("ignoring lastActivityTime 0x%qx, now 0x%qx, wake 0x%qx\n",
2817 		    lastActivityTime, now, gIOLastWakeAbsTime);
2818 		sleepDelay = sleepSlider;
2819 	}
2820 
2821 	DLOG("user inactive %u min, time to idle sleep %u min\n",
2822 	    minutesSinceUserInactive, sleepDelay);
2823 
2824 	return sleepDelay * 60 * 1000;
2825 }
2826 
2827 //******************************************************************************
2828 // setQuickSpinDownTimeout
2829 //
2830 //******************************************************************************
2831 
2832 void
setQuickSpinDownTimeout(void)2833 IOPMrootDomain::setQuickSpinDownTimeout( void )
2834 {
2835 	ASSERT_GATED();
2836 	setAggressiveness(
2837 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
2838 }
2839 
2840 //******************************************************************************
2841 // restoreUserSpinDownTimeout
2842 //
2843 //******************************************************************************
2844 
2845 void
restoreUserSpinDownTimeout(void)2846 IOPMrootDomain::restoreUserSpinDownTimeout( void )
2847 {
2848 	ASSERT_GATED();
2849 	setAggressiveness(
2850 		kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
2851 }
2852 
2853 //******************************************************************************
2854 // sleepSystem
2855 //
2856 //******************************************************************************
2857 
2858 /* public */
2859 IOReturn
sleepSystem(void)2860 IOPMrootDomain::sleepSystem( void )
2861 {
2862 	return sleepSystemOptions(NULL);
2863 }
2864 
2865 /* private */
2866 IOReturn
sleepSystemOptions(OSDictionary * options)2867 IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
2868 {
2869 	OSObject *obj = NULL;
2870 	OSString *reason = NULL;
2871 	/* sleepSystem is a public function, and may be called by any kernel driver.
2872 	 * And that's bad - drivers should sleep the system by calling
2873 	 * receivePowerNotification() instead. Drivers should not use sleepSystem.
2874 	 *
2875 	 * Note that user space app calls to IOPMSleepSystem() will also travel
2876 	 * this code path and thus be correctly identified as software sleeps.
2877 	 */
2878 
2879 	if (options && options->getObject("OSSwitch")) {
2880 		// Log specific sleep cause for OS Switch hibernation
2881 		return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
2882 	}
2883 
2884 	if (options && (obj = options->getObject("Sleep Reason"))) {
2885 		reason = OSDynamicCast(OSString, obj);
2886 		if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey)) {
2887 			return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
2888 		}
2889 		if (reason && reason->isEqualTo(kIOPMNotificationWakeExitKey)) {
2890 			return privateSleepSystem(kIOPMSleepReasonNotificationWakeExit);
2891 		}
2892 	}
2893 
2894 	return privateSleepSystem( kIOPMSleepReasonSoftware);
2895 }
2896 
2897 /* private */
2898 IOReturn
privateSleepSystem(uint32_t sleepReason)2899 IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
2900 {
2901 	/* Called from both gated and non-gated context */
2902 
2903 	if (!checkSystemSleepEnabled() || !pmPowerStateQueue) {
2904 		return kIOReturnNotPermitted;
2905 	}
2906 
2907 	pmPowerStateQueue->submitPowerEvent(
2908 		kPowerEventPolicyStimulus,
2909 		(void *) kStimulusDemandSystemSleep,
2910 		sleepReason);
2911 
2912 	return kIOReturnSuccess;
2913 }
2914 
2915 //******************************************************************************
2916 // powerChangeDone
2917 //
2918 // This overrides powerChangeDone in IOService.
2919 //******************************************************************************
2920 void
powerChangeDone(unsigned long previousPowerState)2921 IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2922 {
2923 #if !__i386__ && !__x86_64__
2924 	uint64_t    timeSinceReset = 0;
2925 #endif
2926 	uint64_t           now;
2927 	unsigned long      newState;
2928 	clock_sec_t        secs;
2929 	clock_usec_t       microsecs;
2930 	uint32_t           lastDebugWakeSeconds;
2931 	clock_sec_t        adjWakeTime;
2932 	IOPMCalendarStruct nowCalendar;
2933 
2934 	ASSERT_GATED();
2935 	newState = getPowerState();
2936 	DLOG("PowerChangeDone: %s->%s\n",
2937 	    getPowerStateString((uint32_t) previousPowerState), getPowerStateString((uint32_t) getPowerState()));
2938 
2939 	if (previousPowerState == newState) {
2940 		return;
2941 	}
2942 
2943 	notifierThread = current_thread();
2944 	switch (getPowerState()) {
2945 	case SLEEP_STATE: {
2946 		if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceWakeupBit)) {
2947 			IOLog("accelerate wake for assertion\n");
2948 			setWakeTime(mach_continuous_time());
2949 		}
2950 		if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionForceFullWakeupBit)) {
2951 			// Note: The scheduled RTC wakeup will trigger a full wake.
2952 			scheduleImmediateDebugWake();
2953 		}
2954 
2955 		if (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector) {
2956 			secs = 0;
2957 			microsecs = 0;
2958 			PEGetUTCTimeOfDay(&secs, &microsecs);
2959 
2960 			adjWakeTime = 0;
2961 			if ((kIOPMAOTModeRespectTimers & _aotMode) && (_calendarWakeAlarmUTC < _aotWakeTimeUTC)) {
2962 				IOLog("use _calendarWakeAlarmUTC\n");
2963 				adjWakeTime = _calendarWakeAlarmUTC;
2964 			} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
2965 				IOLog("accelerate _aotWakeTime for exit\n");
2966 				adjWakeTime = secs;
2967 			} else if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
2968 				IOLog("accelerate _aotWakeTime for assertion\n");
2969 				adjWakeTime = secs;
2970 			}
2971 			if (adjWakeTime) {
2972 				IOPMConvertSecondsToCalendar(adjWakeTime, &_aotWakeTimeCalendar);
2973 			}
2974 
2975 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
2976 			IOLog("aotSleep at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
2977 
2978 			IOReturn __unused ret = setMaintenanceWakeCalendar(&_aotWakeTimeCalendar);
2979 			assert(kIOReturnSuccess == ret);
2980 		}
2981 		if (_aotLastWakeTime) {
2982 			_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
2983 			if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
2984 				strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
2985 				    gWakeReasonString,
2986 				    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
2987 			}
2988 		}
2989 		_aotPendingFlags &= ~kIOPMWakeEventAOTPerCycleFlags;
2990 		if (_aotTimerScheduled) {
2991 			_aotTimerES->cancelTimeout();
2992 			_aotTimerScheduled = false;
2993 		}
2994 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Enable);
2995 
2996 		// re-enable this timer for next sleep
2997 		cancelIdleSleepTimer();
2998 
2999 		if (clamshellExists) {
3000 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
3001 			if (gClamshellFlags & kClamshell_WAR_58009435) {
3002 				// Disable clamshell sleep until system has completed full wake.
3003 				// This prevents a system sleep request (due to a clamshell close)
3004 				// from being queued until the end of system full wake - even if
3005 				// other clamshell disable bits outside of our control is wrong.
3006 				setClamShellSleepDisable(true, kClamshellSleepDisableInternal);
3007 			}
3008 #endif
3009 
3010 			// Log the last known clamshell state before system sleep
3011 			DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
3012 			    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask,
3013 			    desktopMode, acAdaptorConnected);
3014 		}
3015 
3016 		clock_get_calendar_absolute_and_microtime(&secs, &microsecs, &now);
3017 		logtime(secs);
3018 		gIOLastSleepTime.tv_sec  = secs;
3019 		gIOLastSleepTime.tv_usec = microsecs;
3020 		if (!_aotLastWakeTime) {
3021 			gIOLastUserSleepTime = gIOLastSleepTime;
3022 		}
3023 		gIOLastWakeTime.tv_sec = 0;
3024 		gIOLastWakeTime.tv_usec = 0;
3025 		gIOLastSleepAbsTime = now;
3026 
3027 		if (wake2DarkwakeDelay && sleepDelaysReport) {
3028 			clock_sec_t     wake2DarkwakeSecs, darkwake2SleepSecs;
3029 			// Update 'wake2DarkwakeDelay' histogram if this is a fullwake->sleep transition
3030 
3031 			SUB_ABSOLUTETIME(&now, &ts_sleepStart);
3032 			absolutetime_to_microtime(now, &darkwake2SleepSecs, &microsecs);
3033 			absolutetime_to_microtime(wake2DarkwakeDelay, &wake2DarkwakeSecs, &microsecs);
3034 			HISTREPORT_TALLYVALUE(sleepDelaysReport,
3035 			    (int64_t)(wake2DarkwakeSecs + darkwake2SleepSecs));
3036 
3037 			DLOG("Updated sleepDelaysReport %lu %lu\n", (unsigned long)wake2DarkwakeSecs, (unsigned long)darkwake2SleepSecs);
3038 			wake2DarkwakeDelay = 0;
3039 		}
3040 #if HIBERNATION
3041 		LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
3042 #if (DEVELOPMENT || DEBUG)
3043 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
3044 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
3045 		    "System State",
3046 		    gIOHibernateState ? "Enter Hibernate" : "Enter Sleep"
3047 		    );
3048 #endif /* DEVELOPMENT || DEBUG */
3049 		IOHibernateSystemHasSlept();
3050 
3051 		evaluateSystemSleepPolicyFinal();
3052 #else
3053 		LOG("System Sleep\n");
3054 #if (DEVELOPMENT || DEBUG)
3055 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
3056 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
3057 		    "System State", "Enter Sleep");
3058 #endif /* DEVELOPMENT || DEBUG */
3059 #endif
3060 		if (thermalWarningState) {
3061 			OSSharedPtr<const OSSymbol> event = OSSymbol::withCString(kIOPMThermalLevelWarningKey);
3062 			if (event) {
3063 				systemPowerEventOccurred(event.get(), kIOPMThermalLevelUnknown);
3064 			}
3065 		}
3066 		assertOnWakeSecs = 0;
3067 		lowBatteryCondition = false;
3068 		thermalEmergencyState = false;
3069 
3070 #if DEVELOPMENT || DEBUG
3071 		extern int g_should_log_clock_adjustments;
3072 		if (g_should_log_clock_adjustments) {
3073 			clock_sec_t  secs = 0;
3074 			clock_usec_t microsecs = 0;
3075 			uint64_t now_b = mach_absolute_time();
3076 
3077 			secs = 0;
3078 			microsecs = 0;
3079 			PEGetUTCTimeOfDay(&secs, &microsecs);
3080 
3081 			uint64_t now_a = mach_absolute_time();
3082 			os_log(OS_LOG_DEFAULT, "%s PMU before going to sleep %lu s %d u %llu abs_b_PEG %llu abs_a_PEG \n",
3083 			    __func__, (unsigned long)secs, microsecs, now_b, now_a);
3084 		}
3085 #endif
3086 
3087 		getPlatform()->sleepKernel();
3088 
3089 		// The CPU(s) are off at this point,
3090 		// Code will resume execution here upon wake.
3091 
3092 		clock_get_uptime(&gIOLastWakeAbsTime);
3093 		IOLog("gIOLastWakeAbsTime: %lld\n", gIOLastWakeAbsTime);
3094 #if DEVELOPMENT || DEBUG
3095 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
3096 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
3097 		    "System State", "Waking Up"
3098 		    );
3099 #endif /* DEVELOPMENT || DEBUG */
3100 		_highestCapability = 0;
3101 
3102 #if HIBERNATION
3103 		IOHibernateSystemWake();
3104 #endif
3105 
3106 		// sleep transition complete
3107 		gSleepOrShutdownPending = 0;
3108 
3109 		// trip the reset of the calendar clock
3110 		clock_wakeup_calendar();
3111 		clock_get_calendar_microtime(&secs, &microsecs);
3112 		gIOLastWakeTime.tv_sec  = secs;
3113 		gIOLastWakeTime.tv_usec = microsecs;
3114 
3115 		// aot
3116 		if (_aotWakeTimeCalendar.selector != kPMCalendarTypeInvalid) {
3117 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
3118 			secs = 0;
3119 			microsecs = 0;
3120 			PEGetUTCTimeOfDay(&secs, &microsecs);
3121 			IOPMConvertSecondsToCalendar(secs, &nowCalendar);
3122 			IOLog("aotWake at " YMDTF " sched: " YMDTF "\n", YMDT(&nowCalendar), YMDT(&_aotWakeTimeCalendar));
3123 			_aotMetrics->sleepCount++;
3124 			_aotLastWakeTime = gIOLastWakeAbsTime;
3125 			if (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax) {
3126 				_aotMetrics->kernelSleepTime[_aotMetrics->sleepCount - 1]
3127 				        = (((uint64_t) gIOLastSleepTime.tv_sec) << 10) + (gIOLastSleepTime.tv_usec / 1000);
3128 				_aotMetrics->kernelWakeTime[_aotMetrics->sleepCount - 1]
3129 				        = (((uint64_t) gIOLastWakeTime.tv_sec) << 10) + (gIOLastWakeTime.tv_usec / 1000);
3130 			}
3131 
3132 			if (_aotTestTime) {
3133 				if (_aotWakeTimeUTC <= secs) {
3134 					_aotTestTime = mach_continuous_time() + _aotTestInterval;
3135 				}
3136 				if (_aotTestTime < _aotEndTime) {
3137 					_setWakeTime(_aotTestTime);
3138 				}
3139 			}
3140 		}
3141 
3142 #if HIBERNATION
3143 		LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
3144 #endif
3145 
3146 		lastSleepReason = 0;
3147 
3148 		lastDebugWakeSeconds    = _debugWakeSeconds;
3149 		_debugWakeSeconds       = 0;
3150 		_scheduledAlarmMask     = 0;
3151 		_nextScheduledAlarmType = NULL;
3152 
3153 		darkWakeExit            = false;
3154 		darkWakePowerClamped    = false;
3155 		darkWakePostTickle      = false;
3156 		darkWakeHibernateError  = false;
3157 		darkWakeToSleepASAP     = true;
3158 		darkWakeLogClamp        = true;
3159 		sleepTimerMaintenance   = false;
3160 		sleepToStandby          = false;
3161 		wranglerTickled         = false;
3162 		userWasActive           = false;
3163 		isRTCAlarmWake          = false;
3164 		clamshellIgnoreClose    = false;
3165 		fullWakeReason = kFullWakeReasonNone;
3166 		idleSleepRevertible     = true;
3167 
3168 #if defined(__i386__) || defined(__x86_64__)
3169 		kdebugTrace(kPMLogSystemWake, 0, 0, 0);
3170 
3171 		OSSharedPtr<OSObject> wakeTypeProp   = copyProperty(kIOPMRootDomainWakeTypeKey);
3172 		OSSharedPtr<OSObject> wakeReasonProp = copyProperty(kIOPMRootDomainWakeReasonKey);
3173 		OSString * wakeType = OSDynamicCast(OSString, wakeTypeProp.get());
3174 		OSString * wakeReason = OSDynamicCast(OSString, wakeReasonProp.get());
3175 
3176 		if (wakeReason && (wakeReason->getLength() >= 2) &&
3177 		    gWakeReasonString[0] == '\0') {
3178 			WAKEEVENT_LOCK();
3179 			// Until the platform driver can claim its wake reasons
3180 			strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
3181 			    sizeof(gWakeReasonString));
3182 			if (!gWakeReasonSysctlRegistered) {
3183 				gWakeReasonSysctlRegistered = true;
3184 			}
3185 			WAKEEVENT_UNLOCK();
3186 		}
3187 
3188 		if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery)) {
3189 			lowBatteryCondition = true;
3190 			darkWakeMaintenance = true;
3191 		} else {
3192 #if HIBERNATION
3193 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3194 			OSNumber * hibOptions = OSDynamicCast(  OSNumber, hibOptionsProp.get());
3195 			if (hibernateAborted || ((hibOptions &&
3196 			    !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)))) {
3197 				// Hibernate aborted, or EFI brought up graphics
3198 				darkWakeExit = true;
3199 				if (hibernateAborted) {
3200 					DLOG("Hibernation aborted\n");
3201 				} else {
3202 					DLOG("EFI brought up graphics. Going to full wake. HibOptions: 0x%x\n", hibOptions->unsigned32BitValue());
3203 				}
3204 			} else
3205 #endif
3206 			if (wakeType && (
3207 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
3208 				    wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm))) {
3209 				// User wake or RTC alarm
3210 				darkWakeExit = true;
3211 				if (wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)) {
3212 					isRTCAlarmWake = true;
3213 				}
3214 			} else if (wakeType &&
3215 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer)) {
3216 				// SMC standby timer trumps SleepX
3217 				darkWakeMaintenance = true;
3218 				sleepTimerMaintenance = true;
3219 			} else if ((lastDebugWakeSeconds != 0) &&
3220 			    ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0)) {
3221 				// SleepX before maintenance
3222 				darkWakeExit = true;
3223 			} else if (wakeType &&
3224 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance)) {
3225 				darkWakeMaintenance = true;
3226 			} else if (wakeType &&
3227 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService)) {
3228 				darkWakeMaintenance = true;
3229 				darkWakeSleepService = true;
3230 #if HIBERNATION
3231 				if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
3232 					sleepToStandby = true;
3233 				}
3234 #endif
3235 			} else if (wakeType &&
3236 			    wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError)) {
3237 				darkWakeMaintenance = true;
3238 				darkWakeHibernateError = true;
3239 			} else {
3240 				// Unidentified wake source, resume to full wake if debug
3241 				// alarm is pending.
3242 
3243 				if (lastDebugWakeSeconds &&
3244 				    (!wakeReason || wakeReason->isEqualTo(""))) {
3245 					darkWakeExit = true;
3246 				}
3247 			}
3248 		}
3249 
3250 		if (darkWakeExit) {
3251 			darkWakeToSleepASAP = false;
3252 			fullWakeReason = kFullWakeReasonLocalUser;
3253 			reportUserInput();
3254 		} else if (displayPowerOnRequested && checkSystemCanSustainFullWake()) {
3255 			handleSetDisplayPowerOn(true);
3256 		} else if (!darkWakeMaintenance) {
3257 			// Early/late tickle for non-maintenance wake.
3258 			if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) != kDarkWakeFlagPromotionNone) {
3259 				darkWakePostTickle = true;
3260 			}
3261 		}
3262 #else   /* !__i386__ && !__x86_64__ */
3263 		timeSinceReset = ml_get_time_since_reset();
3264 		kdebugTrace(kPMLogSystemWake, 0, (uintptr_t)(timeSinceReset >> 32), (uintptr_t) timeSinceReset);
3265 
3266 		if ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) == kDarkWakeFlagPromotionEarly) {
3267 			wranglerTickled = true;
3268 			fullWakeReason = kFullWakeReasonLocalUser;
3269 			requestUserActive(this, "Full wake on dark wake promotion boot-arg");
3270 		} else if ((lastDebugWakeSeconds != 0) && !(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
3271 			isRTCAlarmWake = true;
3272 			fullWakeReason = kFullWakeReasonLocalUser;
3273 			requestUserActive(this, "RTC debug alarm");
3274 		} else {
3275 #if HIBERNATION
3276 			OSSharedPtr<OSObject> hibOptionsProp = copyProperty(kIOHibernateOptionsKey);
3277 			OSNumber * hibOptions = OSDynamicCast(OSNumber, hibOptionsProp.get());
3278 			if (hibOptions && !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake)) {
3279 				fullWakeReason = kFullWakeReasonLocalUser;
3280 				requestUserActive(this, "hibernate user wake");
3281 			}
3282 #endif
3283 		}
3284 
3285 		// stay awake for at least 30 seconds
3286 		startIdleSleepTimer(30 * 1000);
3287 #endif
3288 		sleepCnt++;
3289 
3290 		thread_call_enter(updateConsoleUsersEntry);
3291 
3292 		// Skip AOT_STATE if we are waking up from an RTC timer.
3293 		// This check needs to be done after the epoch change is processed
3294 		// and before the changePowerStateWithTagToPriv() call below.
3295 		WAKEEVENT_LOCK();
3296 		aotShouldExit(false);
3297 		unsigned long newState = getRUN_STATE();
3298 		if (AOT_STATE == newState) {
3299 			_aotRunMode = gLPWFlags;
3300 		}
3301 		WAKEEVENT_UNLOCK();
3302 
3303 		changePowerStateWithTagToPriv(newState, kCPSReasonWake);
3304 		break;
3305 	}
3306 #if !__i386__ && !__x86_64__
3307 	case ON_STATE:
3308 	case AOT_STATE:
3309 	{
3310 		DLOG("Force re-evaluating aggressiveness\n");
3311 		/* Force re-evaluate the aggressiveness values to set appropriate idle sleep timer */
3312 		pmPowerStateQueue->submitPowerEvent(
3313 			kPowerEventPolicyStimulus,
3314 			(void *) kStimulusNoIdleSleepPreventers );
3315 
3316 		// After changing to ON_STATE, invalidate any previously queued
3317 		// request to change to a state less than ON_STATE. This isn't
3318 		// necessary for AOT_STATE or if the device has only one running
3319 		// state since the changePowerStateToPriv() issued at the tail
3320 		// end of SLEEP_STATE case should take care of that.
3321 		if (getPowerState() == ON_STATE) {
3322 			changePowerStateWithTagToPriv(ON_STATE, kCPSReasonWake);
3323 		}
3324 		break;
3325 	}
3326 #endif /* !__i386__ && !__x86_64__ */
3327 	}
3328 	notifierThread = NULL;
3329 }
3330 
3331 //******************************************************************************
3332 // requestPowerDomainState
3333 //
3334 // Extend implementation in IOService. Running on PM work loop thread.
3335 //******************************************************************************
3336 
3337 IOReturn
requestPowerDomainState(IOPMPowerFlags childDesire,IOPowerConnection * childConnection,unsigned long specification)3338 IOPMrootDomain::requestPowerDomainState(
3339 	IOPMPowerFlags      childDesire,
3340 	IOPowerConnection * childConnection,
3341 	unsigned long       specification )
3342 {
3343 	// Idle and system sleep prevention flags affects driver desire.
3344 	// Children desire are irrelevant so they are cleared.
3345 
3346 	return super::requestPowerDomainState(0, childConnection, specification);
3347 }
3348 
3349 
3350 static void
makeSleepPreventersListLog(const OSSharedPtr<OSSet> & preventers,char * buf,size_t buf_size)3351 makeSleepPreventersListLog(const OSSharedPtr<OSSet> &preventers, char *buf, size_t buf_size)
3352 {
3353 	if (!preventers->getCount()) {
3354 		return;
3355 	}
3356 
3357 	char *buf_iter = buf + strlen(buf);
3358 	char *buf_end = buf + buf_size;
3359 
3360 	OSSharedPtr<OSCollectionIterator> iterator = OSCollectionIterator::withCollection(preventers.get());
3361 	OSObject *obj = NULL;
3362 
3363 	while ((obj = iterator->getNextObject())) {
3364 		IOService *srv = OSDynamicCast(IOService, obj);
3365 		if (buf_iter < buf_end) {
3366 			buf_iter += snprintf(buf_iter, buf_end - buf_iter, " %s", srv->getName());
3367 		} else {
3368 			DLOG("Print buffer exhausted for sleep preventers list\n");
3369 			break;
3370 		}
3371 	}
3372 }
3373 
3374 //******************************************************************************
3375 // updatePreventIdleSleepList
3376 //
3377 // Called by IOService on PM work loop.
3378 // Returns true if PM policy recognized the driver's desire to prevent idle
3379 // sleep and updated the list of idle sleep preventers. Returns false otherwise
3380 //******************************************************************************
3381 
3382 bool
updatePreventIdleSleepList(IOService * service,bool addNotRemove)3383 IOPMrootDomain::updatePreventIdleSleepList(
3384 	IOService * service, bool addNotRemove)
3385 {
3386 	unsigned int oldCount;
3387 
3388 	oldCount = idleSleepPreventersCount();
3389 	return updatePreventIdleSleepListInternal(service, addNotRemove, oldCount);
3390 }
3391 
3392 bool
updatePreventIdleSleepListInternal(IOService * service,bool addNotRemove,unsigned int oldCount)3393 IOPMrootDomain::updatePreventIdleSleepListInternal(
3394 	IOService * service, bool addNotRemove, unsigned int oldCount)
3395 {
3396 	unsigned int newCount;
3397 
3398 	ASSERT_GATED();
3399 
3400 #if defined(XNU_TARGET_OS_OSX)
3401 	// Only the display wrangler and no-idle-sleep kernel assertions
3402 	// can prevent idle sleep. The kIOPMPreventIdleSleep capability flag
3403 	// reported by drivers in their power state table is ignored.
3404 	if (service && (service != wrangler) && (service != this)) {
3405 		return false;
3406 	}
3407 #endif
3408 
3409 	if (service) {
3410 		if (addNotRemove) {
3411 			preventIdleSleepList->setObject(service);
3412 			DLOG("Added %s to idle sleep preventers list (Total %u)\n",
3413 			    service->getName(), preventIdleSleepList->getCount());
3414 		} else if (preventIdleSleepList->member(service)) {
3415 			preventIdleSleepList->removeObject(service);
3416 			DLOG("Removed %s from idle sleep preventers list (Total %u)\n",
3417 			    service->getName(), preventIdleSleepList->getCount());
3418 		}
3419 
3420 		if (preventIdleSleepList->getCount()) {
3421 			char buf[256] = "Idle Sleep Preventers:";
3422 			makeSleepPreventersListLog(preventIdleSleepList, buf, sizeof(buf));
3423 			DLOG("%s\n", buf);
3424 		}
3425 	}
3426 
3427 	newCount = idleSleepPreventersCount();
3428 
3429 	if ((oldCount == 0) && (newCount != 0)) {
3430 		// Driver added to empty prevent list.
3431 		// Update the driver desire to prevent idle sleep.
3432 		// Driver desire does not prevent demand sleep.
3433 
3434 		changePowerStateWithTagTo(getRUN_STATE(), kCPSReasonIdleSleepPrevent);
3435 	} else if ((oldCount != 0) && (newCount == 0)) {
3436 		// Last driver removed from prevent list.
3437 		// Drop the driver clamp to allow idle sleep.
3438 
3439 		changePowerStateWithTagTo(SLEEP_STATE, kCPSReasonIdleSleepAllow);
3440 		evaluatePolicy( kStimulusNoIdleSleepPreventers );
3441 	}
3442 	messageClient(kIOPMMessageIdleSleepPreventers, systemCapabilityNotifier.get(),
3443 	    &newCount, sizeof(newCount));
3444 
3445 #if defined(XNU_TARGET_OS_OSX)
3446 	if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake()) {
3447 		DLOG("Cannot cancel idle sleep\n");
3448 		return false; // do not idle-cancel
3449 	}
3450 #endif
3451 
3452 	return true;
3453 }
3454 
3455 //******************************************************************************
3456 // startSpinDump
3457 //******************************************************************************
3458 
3459 void
startSpinDump(uint32_t spindumpKind)3460 IOPMrootDomain::startSpinDump(uint32_t spindumpKind)
3461 {
3462 	messageClients(kIOPMMessageLaunchBootSpinDump, (void *)(uintptr_t)spindumpKind);
3463 }
3464 
3465 //******************************************************************************
3466 // preventSystemSleepListUpdate
3467 //
3468 // Called by IOService on PM work loop.
3469 //******************************************************************************
3470 
3471 void
updatePreventSystemSleepList(IOService * service,bool addNotRemove)3472 IOPMrootDomain::updatePreventSystemSleepList(
3473 	IOService * service, bool addNotRemove )
3474 {
3475 	unsigned int oldCount, newCount;
3476 
3477 	ASSERT_GATED();
3478 	if (this == service) {
3479 		return;
3480 	}
3481 
3482 	oldCount = preventSystemSleepList->getCount();
3483 	if (addNotRemove) {
3484 		preventSystemSleepList->setObject(service);
3485 		DLOG("Added %s to system sleep preventers list (Total %u)\n",
3486 		    service->getName(), preventSystemSleepList->getCount());
3487 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
3488 			AbsoluteTime    now;
3489 			clock_usec_t    microsecs;
3490 			clock_get_uptime(&now);
3491 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
3492 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
3493 			if (assertOnWakeReport) {
3494 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
3495 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
3496 			}
3497 		}
3498 	} else if (preventSystemSleepList->member(service)) {
3499 		preventSystemSleepList->removeObject(service);
3500 		DLOG("Removed %s from system sleep preventers list (Total %u)\n",
3501 		    service->getName(), preventSystemSleepList->getCount());
3502 
3503 		if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0)) {
3504 			// Lost all system sleep preventers.
3505 			// Send stimulus if system sleep was blocked, and is in dark wake.
3506 			evaluatePolicy( kStimulusDarkWakeEvaluate );
3507 		}
3508 	}
3509 
3510 	newCount = preventSystemSleepList->getCount();
3511 	if (newCount) {
3512 		char buf[256] = "System Sleep Preventers:";
3513 		makeSleepPreventersListLog(preventSystemSleepList, buf, sizeof(buf));
3514 		DLOG("%s\n", buf);
3515 	}
3516 
3517 	messageClient(kIOPMMessageSystemSleepPreventers, systemCapabilityNotifier.get(),
3518 	    &newCount, sizeof(newCount));
3519 }
3520 
3521 void
copySleepPreventersList(OSArray ** idleSleepList,OSArray ** systemSleepList)3522 IOPMrootDomain::copySleepPreventersList(OSArray **idleSleepList, OSArray **systemSleepList)
3523 {
3524 	OSSharedPtr<OSCollectionIterator> iterator;
3525 	OSObject    *object = NULL;
3526 	OSSharedPtr<OSArray>     array;
3527 
3528 	if (!gIOPMWorkLoop->inGate()) {
3529 		gIOPMWorkLoop->runAction(
3530 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3531 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersList),
3532 			this, (void *)idleSleepList, (void *)systemSleepList);
3533 		return;
3534 	}
3535 
3536 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3537 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3538 		array = OSArray::withCapacity(5);
3539 
3540 		if (iterator && array) {
3541 			while ((object = iterator->getNextObject())) {
3542 				IOService *service = OSDynamicCast(IOService, object);
3543 				if (service) {
3544 					OSSharedPtr<const OSSymbol> name = service->copyName();
3545 					if (name) {
3546 						array->setObject(name.get());
3547 					}
3548 				}
3549 			}
3550 		}
3551 		*idleSleepList = array.detach();
3552 	}
3553 
3554 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3555 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3556 		array = OSArray::withCapacity(5);
3557 
3558 		if (iterator && array) {
3559 			while ((object = iterator->getNextObject())) {
3560 				IOService *service = OSDynamicCast(IOService, object);
3561 				if (service) {
3562 					OSSharedPtr<const OSSymbol> name = service->copyName();
3563 					if (name) {
3564 						array->setObject(name.get());
3565 					}
3566 				}
3567 			}
3568 		}
3569 		*systemSleepList = array.detach();
3570 	}
3571 }
3572 
3573 void
copySleepPreventersListWithID(OSArray ** idleSleepList,OSArray ** systemSleepList)3574 IOPMrootDomain::copySleepPreventersListWithID(OSArray **idleSleepList, OSArray **systemSleepList)
3575 {
3576 	OSSharedPtr<OSCollectionIterator> iterator;
3577 	OSObject    *object = NULL;
3578 	OSSharedPtr<OSArray>     array;
3579 
3580 	if (!gIOPMWorkLoop->inGate()) {
3581 		gIOPMWorkLoop->runAction(
3582 			OSMemberFunctionCast(IOWorkLoop::Action, this,
3583 			&IOPMrootDomain::IOPMrootDomain::copySleepPreventersListWithID),
3584 			this, (void *)idleSleepList, (void *)systemSleepList);
3585 		return;
3586 	}
3587 
3588 	if (idleSleepList && preventIdleSleepList && (preventIdleSleepList->getCount() != 0)) {
3589 		iterator = OSCollectionIterator::withCollection(preventIdleSleepList.get());
3590 		array = OSArray::withCapacity(5);
3591 
3592 		if (iterator && array) {
3593 			while ((object = iterator->getNextObject())) {
3594 				IOService *service = OSDynamicCast(IOService, object);
3595 				if (service) {
3596 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3597 					OSSharedPtr<const OSSymbol> name = service->copyName();
3598 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3599 					if (dict && name && id) {
3600 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3601 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3602 						array->setObject(dict.get());
3603 					}
3604 				}
3605 			}
3606 		}
3607 		*idleSleepList = array.detach();
3608 	}
3609 
3610 	if (systemSleepList && preventSystemSleepList && (preventSystemSleepList->getCount() != 0)) {
3611 		iterator = OSCollectionIterator::withCollection(preventSystemSleepList.get());
3612 		array = OSArray::withCapacity(5);
3613 
3614 		if (iterator && array) {
3615 			while ((object = iterator->getNextObject())) {
3616 				IOService *service = OSDynamicCast(IOService, object);
3617 				if (service) {
3618 					OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(2);
3619 					OSSharedPtr<const OSSymbol> name = service->copyName();
3620 					OSSharedPtr<OSNumber> id = OSNumber::withNumber(service->getRegistryEntryID(), 64);
3621 					if (dict && name && id) {
3622 						dict->setObject(kIOPMDriverAssertionRegistryEntryIDKey, id.get());
3623 						dict->setObject(kIOPMDriverAssertionOwnerStringKey, name.get());
3624 						array->setObject(dict.get());
3625 					}
3626 				}
3627 			}
3628 		}
3629 		*systemSleepList = array.detach();
3630 	}
3631 }
3632 
3633 //******************************************************************************
3634 // tellChangeDown
3635 //
3636 // Override the superclass implementation to send a different message type.
3637 //******************************************************************************
3638 
3639 bool
tellChangeDown(unsigned long stateNum)3640 IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3641 {
3642 	DLOG("tellChangeDown %s->%s\n",
3643 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3644 
3645 	if (SLEEP_STATE == stateNum) {
3646 		// Legacy apps were already told in the full->dark transition
3647 		if (!ignoreTellChangeDown) {
3648 			tracePoint( kIOPMTracePointSleepApplications );
3649 		} else {
3650 			tracePoint( kIOPMTracePointSleepPriorityClients );
3651 		}
3652 	}
3653 
3654 	if (!ignoreTellChangeDown) {
3655 		userActivityAtSleep = userActivityCount;
3656 		DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3657 
3658 		if (SLEEP_STATE == stateNum) {
3659 			hibernateAborted = false;
3660 
3661 			// Direct callout into OSKext so it can disable kext unloads
3662 			// during sleep/wake to prevent deadlocks.
3663 			OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3664 
3665 			IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
3666 
3667 			// Two change downs are sent by IOServicePM. Ignore the 2nd.
3668 			// But tellClientsWithResponse() must be called for both.
3669 			ignoreTellChangeDown = true;
3670 		}
3671 	}
3672 
3673 	return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
3674 }
3675 
3676 //******************************************************************************
3677 // askChangeDown
3678 //
3679 // Override the superclass implementation to send a different message type.
3680 // This must be idle sleep since we don't ask during any other power change.
3681 //******************************************************************************
3682 
3683 bool
askChangeDown(unsigned long stateNum)3684 IOPMrootDomain::askChangeDown( unsigned long stateNum )
3685 {
3686 	DLOG("askChangeDown %s->%s\n",
3687 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3688 
3689 	// Don't log for dark wake entry
3690 	if (kSystemTransitionSleep == _systemTransitionType) {
3691 		tracePoint( kIOPMTracePointSleepApplications );
3692 	}
3693 
3694 	return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
3695 }
3696 
3697 //******************************************************************************
3698 // askChangeDownDone
3699 //
3700 // An opportunity for root domain to cancel the power transition,
3701 // possibily due to an assertion created by powerd in response to
3702 // kIOMessageCanSystemSleep.
3703 //
3704 // Idle sleep:
3705 //   full -> dark wake transition
3706 //     1. Notify apps and powerd with kIOMessageCanSystemSleep
3707 //     2. askChangeDownDone()
3708 //   dark -> sleep transition
3709 //     1. Notify powerd with kIOMessageCanSystemSleep
3710 //     2. askChangeDownDone()
3711 //
3712 // Demand sleep:
3713 //   full -> dark wake transition
3714 //     1. Notify powerd with kIOMessageCanSystemSleep
3715 //     2. askChangeDownDone()
3716 //   dark -> sleep transition
3717 //     1. Notify powerd with kIOMessageCanSystemSleep
3718 //     2. askChangeDownDone()
3719 //******************************************************************************
3720 
3721 void
askChangeDownDone(IOPMPowerChangeFlags * inOutChangeFlags,bool * cancel)3722 IOPMrootDomain::askChangeDownDone(
3723 	IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
3724 {
3725 	DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
3726 	    *inOutChangeFlags, *cancel,
3727 	    _systemTransitionType,
3728 	    _currentCapability, _pendingCapability);
3729 
3730 	if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType)) {
3731 		// Dark->Sleep transition.
3732 		// Check if there are any deny sleep assertions.
3733 		// lastSleepReason already set by handleOurPowerChangeStart()
3734 
3735 		if (!checkSystemCanSleep(lastSleepReason)) {
3736 			// Cancel dark wake to sleep transition.
3737 			// Must re-scan assertions upon entering dark wake.
3738 
3739 			*cancel = true;
3740 			DLOG("cancel dark->sleep\n");
3741 		}
3742 		if (_aotMode && (kPMCalendarTypeInvalid != _aotWakeTimeCalendar.selector)) {
3743 			uint64_t now = mach_continuous_time();
3744 			if (((now + _aotWakePreWindow) >= _aotWakeTimeContinuous)
3745 			    && (now < (_aotWakeTimeContinuous + _aotWakePostWindow))) {
3746 				*cancel = true;
3747 				IOLog("AOT wake window cancel: %qd, %qd\n", now, _aotWakeTimeContinuous);
3748 			}
3749 		}
3750 	}
3751 }
3752 
3753 //******************************************************************************
3754 // systemDidNotSleep
3755 //
3756 // Work common to both canceled or aborted sleep.
3757 //******************************************************************************
3758 
3759 void
systemDidNotSleep(void)3760 IOPMrootDomain::systemDidNotSleep( void )
3761 {
3762 	// reset console lock state
3763 	thread_call_enter(updateConsoleUsersEntry);
3764 
3765 	if (idleSleepEnabled) {
3766 		if (!wrangler) {
3767 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
3768 			startIdleSleepTimer(kIdleSleepRetryInterval);
3769 #else
3770 			startIdleSleepTimer(idleMilliSeconds);
3771 #endif
3772 		} else if (!userIsActive) {
3773 			// Manually start the idle sleep timer besides waiting for
3774 			// the user to become inactive.
3775 			startIdleSleepTimer(kIdleSleepRetryInterval);
3776 		}
3777 	}
3778 
3779 	preventTransitionToUserActive(false);
3780 	IOService::setAdvisoryTickleEnable( true );
3781 	idleSleepRevertible = true;
3782 
3783 	// After idle revert and cancel, send a did-change message to powerd
3784 	// to balance the previous will-change message. Kernel clients do not
3785 	// need this since sleep cannot be canceled once they are notified.
3786 
3787 	if (toldPowerdCapWillChange && systemCapabilityNotifier &&
3788 	    (_pendingCapability != _currentCapability) &&
3789 	    ((_systemMessageClientMask & kSystemMessageClientPowerd) != 0)) {
3790 		// Differs from a real capability gain change where notifyRef != 0,
3791 		// but it is zero here since no response is expected.
3792 
3793 		IOPMSystemCapabilityChangeParameters params;
3794 
3795 		bzero(&params, sizeof(params));
3796 		params.fromCapabilities = _pendingCapability;
3797 		params.toCapabilities = _currentCapability;
3798 		params.changeFlags = kIOPMSystemCapabilityDidChange;
3799 
3800 		DLOG("MESG cap %x->%x did change\n",
3801 		    params.fromCapabilities, params.toCapabilities);
3802 		messageClient(kIOMessageSystemCapabilityChange, systemCapabilityNotifier.get(),
3803 		    &params, sizeof(params));
3804 	}
3805 }
3806 
3807 //******************************************************************************
3808 // tellNoChangeDown
3809 //
3810 // Notify registered applications and kernel clients that we are not dropping
3811 // power.
3812 //
3813 // We override the superclass implementation so we can send a different message
3814 // type to the client or application being notified.
3815 //
3816 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3817 //******************************************************************************
3818 
3819 void
tellNoChangeDown(unsigned long stateNum)3820 IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3821 {
3822 	DLOG("tellNoChangeDown %s->%s\n",
3823 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3824 
3825 	// Sleep canceled, clear the sleep trace point.
3826 	tracePoint(kIOPMTracePointSystemUp);
3827 
3828 	systemDidNotSleep();
3829 	return tellClients( kIOMessageSystemWillNotSleep );
3830 }
3831 
3832 //******************************************************************************
3833 // tellChangeUp
3834 //
3835 // Notify registered applications and kernel clients that we are raising power.
3836 //
3837 // We override the superclass implementation so we can send a different message
3838 // type to the client or application being notified.
3839 //******************************************************************************
3840 
3841 void
tellChangeUp(unsigned long stateNum)3842 IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3843 {
3844 	DLOG("tellChangeUp %s->%s\n",
3845 	    getPowerStateString((uint32_t) getPowerState()), getPowerStateString((uint32_t) stateNum));
3846 
3847 	ignoreTellChangeDown = false;
3848 
3849 	if (stateNum == ON_STATE) {
3850 		// Direct callout into OSKext so it can disable kext unloads
3851 		// during sleep/wake to prevent deadlocks.
3852 		OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3853 
3854 		// Notify platform that sleep was cancelled or resumed.
3855 		getPlatform()->callPlatformFunction(
3856 			sleepMessagePEFunction.get(), false,
3857 			(void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3858 			NULL, NULL, NULL);
3859 
3860 		if (getPowerState() == ON_STATE) {
3861 			// Sleep was cancelled by idle cancel or revert
3862 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
3863 				// rdar://problem/50363791
3864 				// If system is in dark wake and sleep is cancelled, do not
3865 				// send SystemWillPowerOn/HasPoweredOn messages to kernel
3866 				// priority clients. They haven't yet seen a SystemWillSleep
3867 				// message before the cancellation. So make sure the kernel
3868 				// client bit is cleared in _systemMessageClientMask before
3869 				// invoking the tellClients() below. This bit may have been
3870 				// set by handleOurPowerChangeStart() anticipating a successful
3871 				// sleep and setting the filter mask ahead of time allows the
3872 				// SystemWillSleep message to go through.
3873 				_systemMessageClientMask &= ~kSystemMessageClientKernel;
3874 			}
3875 
3876 			systemDidNotSleep();
3877 			tellClients( kIOMessageSystemWillPowerOn );
3878 		}
3879 
3880 		tracePoint( kIOPMTracePointWakeApplications );
3881 		tellClients( kIOMessageSystemHasPoweredOn );
3882 	} else if (stateNum == AOT_STATE) {
3883 		if (getPowerState() == AOT_STATE) {
3884 			// Sleep was cancelled by idle cancel or revert
3885 			startIdleSleepTimer(idleMilliSeconds);
3886 		}
3887 	}
3888 }
3889 
3890 #define CAP_WILL_CHANGE_TO_OFF(params, flag) \
3891     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3892      ((params)->fromCapabilities & (flag)) && \
3893      (((params)->toCapabilities & (flag)) == 0))
3894 
3895 #define CAP_DID_CHANGE_TO_ON(params, flag) \
3896     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3897      ((params)->toCapabilities & (flag)) && \
3898      (((params)->fromCapabilities & (flag)) == 0))
3899 
3900 #define CAP_DID_CHANGE_TO_OFF(params, flag) \
3901     (((params)->changeFlags & kIOPMSystemCapabilityDidChange) && \
3902      ((params)->fromCapabilities & (flag)) && \
3903      (((params)->toCapabilities & (flag)) == 0))
3904 
3905 #define CAP_WILL_CHANGE_TO_ON(params, flag) \
3906     (((params)->changeFlags & kIOPMSystemCapabilityWillChange) && \
3907      ((params)->toCapabilities & (flag)) && \
3908      (((params)->fromCapabilities & (flag)) == 0))
3909 
3910 //******************************************************************************
3911 // sysPowerDownHandler
3912 //
3913 // Perform a vfs sync before system sleep.
3914 //******************************************************************************
3915 
3916 IOReturn
sysPowerDownHandler(void * target,void * refCon,UInt32 messageType,IOService * service,void * messageArgs,vm_size_t argSize)3917 IOPMrootDomain::sysPowerDownHandler(
3918 	void * target, void * refCon,
3919 	UInt32 messageType, IOService * service,
3920 	void * messageArgs, vm_size_t argSize )
3921 {
3922 	static UInt32 lastSystemMessageType = 0;
3923 	IOReturn    ret = 0;
3924 
3925 	DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
3926 
3927 	// rdar://problem/50363791
3928 	// Sanity check to make sure the SystemWill/Has message types are
3929 	// received in the expected order for all kernel priority clients.
3930 	if (messageType == kIOMessageSystemWillSleep ||
3931 	    messageType == kIOMessageSystemWillPowerOn ||
3932 	    messageType == kIOMessageSystemHasPoweredOn) {
3933 		switch (messageType) {
3934 		case kIOMessageSystemWillPowerOn:
3935 			assert(lastSystemMessageType == kIOMessageSystemWillSleep);
3936 			break;
3937 		case kIOMessageSystemHasPoweredOn:
3938 			assert(lastSystemMessageType == kIOMessageSystemWillPowerOn);
3939 			break;
3940 		}
3941 
3942 		lastSystemMessageType = messageType;
3943 	}
3944 
3945 	if (!gRootDomain) {
3946 		return kIOReturnUnsupported;
3947 	}
3948 
3949 	if (messageType == kIOMessageSystemCapabilityChange) {
3950 		IOPMSystemCapabilityChangeParameters * params =
3951 		    (IOPMSystemCapabilityChangeParameters *) messageArgs;
3952 
3953 		// Interested applications have been notified of an impending power
3954 		// change and have acked (when applicable).
3955 		// This is our chance to save whatever state we can before powering
3956 		// down.
3957 		// We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
3958 		// via callout
3959 
3960 		DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
3961 		    params->fromCapabilities, params->toCapabilities,
3962 		    params->changeFlags);
3963 
3964 		if (CAP_WILL_CHANGE_TO_OFF(params, kIOPMSystemCapabilityCPU)) {
3965 			// We will ack within 20 seconds
3966 			params->maxWaitForReply = 20 * 1000 * 1000;
3967 
3968 #if HIBERNATION
3969 			gRootDomain->evaluateSystemSleepPolicyEarly();
3970 
3971 			// add in time we could spend freeing pages
3972 			if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled) {
3973 				params->maxWaitForReply = kCapabilityClientMaxWait;
3974 			}
3975 			DLOG("sysPowerDownHandler max wait %d s\n",
3976 			    (int) (params->maxWaitForReply / 1000 / 1000));
3977 #endif
3978 
3979 			// Notify platform that sleep has begun, after the early
3980 			// sleep policy evaluation.
3981 			getPlatform()->callPlatformFunction(
3982 				sleepMessagePEFunction.get(), false,
3983 				(void *)(uintptr_t) kIOMessageSystemWillSleep,
3984 				NULL, NULL, NULL);
3985 
3986 			if (!OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending )) {
3987 				// Purposely delay the ack and hope that shutdown occurs quickly.
3988 				// Another option is not to schedule the thread and wait for
3989 				// ack timeout...
3990 				AbsoluteTime deadline;
3991 				clock_interval_to_deadline( 30, kSecondScale, &deadline );
3992 				thread_call_enter1_delayed(
3993 					gRootDomain->diskSyncCalloutEntry,
3994 					(thread_call_param_t)(uintptr_t) params->notifyRef,
3995 					deadline );
3996 			} else {
3997 				thread_call_enter1(
3998 					gRootDomain->diskSyncCalloutEntry,
3999 					(thread_call_param_t)(uintptr_t) params->notifyRef);
4000 			}
4001 		}
4002 #if HIBERNATION
4003 		else if (CAP_DID_CHANGE_TO_ON(params, kIOPMSystemCapabilityCPU)) {
4004 			// We will ack within 110 seconds
4005 			params->maxWaitForReply = 110 * 1000 * 1000;
4006 
4007 			thread_call_enter1(
4008 				gRootDomain->diskSyncCalloutEntry,
4009 				(thread_call_param_t)(uintptr_t) params->notifyRef);
4010 		}
4011 #endif
4012 		ret = kIOReturnSuccess;
4013 	}
4014 
4015 	return ret;
4016 }
4017 
4018 //******************************************************************************
4019 // handleQueueSleepWakeUUID
4020 //
4021 // Called from IOPMrootDomain when we're initiating a sleep,
4022 // or indirectly from PM configd when PM decides to clear the UUID.
4023 // PM clears the UUID several minutes after successful wake from sleep,
4024 // so that we might associate App spindumps with the immediately previous
4025 // sleep/wake.
4026 //
4027 // @param   obj has a retain on it. We're responsible for releasing that retain.
4028 //******************************************************************************
4029 
4030 void
handleQueueSleepWakeUUID(OSObject * obj)4031 IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
4032 {
4033 	OSSharedPtr<OSString>    str;
4034 
4035 	if (kOSBooleanFalse == obj) {
4036 		handlePublishSleepWakeUUID(false);
4037 	} else {
4038 		str.reset(OSDynamicCast(OSString, obj), OSNoRetain);
4039 		if (str) {
4040 			// This branch caches the UUID for an upcoming sleep/wake
4041 			queuedSleepWakeUUIDString = str;
4042 			DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
4043 		}
4044 	}
4045 }
4046 //******************************************************************************
4047 // handlePublishSleepWakeUUID
4048 //
4049 // Called from IOPMrootDomain when we're initiating a sleep,
4050 // or indirectly from PM configd when PM decides to clear the UUID.
4051 // PM clears the UUID several minutes after successful wake from sleep,
4052 // so that we might associate App spindumps with the immediately previous
4053 // sleep/wake.
4054 //******************************************************************************
4055 
4056 void
handlePublishSleepWakeUUID(bool shouldPublish)4057 IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
4058 {
4059 	ASSERT_GATED();
4060 
4061 	/*
4062 	 * Clear the current UUID
4063 	 */
4064 	if (gSleepWakeUUIDIsSet) {
4065 		DLOG("SleepWake UUID cleared\n");
4066 
4067 		gSleepWakeUUIDIsSet = false;
4068 
4069 		removeProperty(kIOPMSleepWakeUUIDKey);
4070 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
4071 	}
4072 
4073 	/*
4074 	 * Optionally, publish a new UUID
4075 	 */
4076 	if (queuedSleepWakeUUIDString && shouldPublish) {
4077 		OSSharedPtr<OSString> publishThisUUID;
4078 
4079 		publishThisUUID = queuedSleepWakeUUIDString;
4080 
4081 		if (publishThisUUID) {
4082 			setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID.get());
4083 		}
4084 
4085 		gSleepWakeUUIDIsSet = true;
4086 		messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
4087 
4088 		queuedSleepWakeUUIDString.reset();
4089 	}
4090 }
4091 
4092 //******************************************************************************
4093 // IOPMGetSleepWakeUUIDKey
4094 //
4095 // Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key.
4096 // To get the full key -- a C string -- the buffer must large enough for
4097 // the end-of-string character.
4098 // The key is expected to be an UUID string
4099 //******************************************************************************
4100 
4101 extern "C" bool
IOPMCopySleepWakeUUIDKey(char * buffer,size_t buf_len)4102 IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len)
4103 {
4104 	if (!gSleepWakeUUIDIsSet) {
4105 		return false;
4106 	}
4107 
4108 	if (buffer != NULL) {
4109 		OSSharedPtr<OSString> string =
4110 		    OSDynamicPtrCast<OSString>(gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey));
4111 
4112 		if (!string) {
4113 			*buffer = '\0';
4114 		} else {
4115 			strlcpy(buffer, string->getCStringNoCopy(), buf_len);
4116 		}
4117 	}
4118 
4119 	return true;
4120 }
4121 
4122 //******************************************************************************
4123 // lowLatencyAudioNotify
4124 //
4125 // Used to send an update about low latency audio activity to interested
4126 // clients. To keep the overhead minimal the OSDictionary used here
4127 // is initialized at boot.
4128 //******************************************************************************
4129 
4130 void
lowLatencyAudioNotify(uint64_t time,boolean_t state)4131 IOPMrootDomain::lowLatencyAudioNotify(uint64_t time, boolean_t state)
4132 {
4133 	if (lowLatencyAudioNotifierDict && lowLatencyAudioNotifyStateSym && lowLatencyAudioNotifyTimestampSym &&
4134 	    lowLatencyAudioNotifyStateVal && lowLatencyAudioNotifyTimestampVal) {
4135 		lowLatencyAudioNotifyTimestampVal->setValue(time);
4136 		lowLatencyAudioNotifyStateVal->setValue(state);
4137 		setPMSetting(gIOPMSettingLowLatencyAudioModeKey.get(), lowLatencyAudioNotifierDict.get());
4138 	} else {
4139 		DLOG("LowLatencyAudioNotify error\n");
4140 	}
4141 	return;
4142 }
4143 
4144 //******************************************************************************
4145 // IOPMrootDomainRTNotifier
4146 //
4147 // Used by performance controller to update the timestamp and state associated
4148 // with low latency audio activity in the system.
4149 //******************************************************************************
4150 
4151 extern "C" void
IOPMrootDomainRTNotifier(uint64_t time,boolean_t state)4152 IOPMrootDomainRTNotifier(uint64_t time, boolean_t state)
4153 {
4154 	gRootDomain->lowLatencyAudioNotify(time, state);
4155 	return;
4156 }
4157 
4158 //******************************************************************************
4159 // initializeBootSessionUUID
4160 //
4161 // Initialize the boot session uuid at boot up and sets it into registry.
4162 //******************************************************************************
4163 
4164 void
initializeBootSessionUUID(void)4165 IOPMrootDomain::initializeBootSessionUUID(void)
4166 {
4167 	uuid_t          new_uuid;
4168 	uuid_string_t   new_uuid_string;
4169 
4170 	uuid_generate(new_uuid);
4171 	uuid_unparse_upper(new_uuid, new_uuid_string);
4172 	memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
4173 
4174 	setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
4175 }
4176 
4177 //******************************************************************************
4178 // Root domain uses the private and tagged changePowerState methods for
4179 // tracking and logging purposes.
4180 //******************************************************************************
4181 
4182 #define REQUEST_TAG_TO_REASON(x)        ((uint16_t)x)
4183 
4184 static uint32_t
nextRequestTag(IOPMRequestTag tag)4185 nextRequestTag( IOPMRequestTag tag )
4186 {
4187 	static SInt16 msb16 = 1;
4188 	uint16_t id = OSAddAtomic16(1, &msb16);
4189 	return ((uint32_t)id << 16) | REQUEST_TAG_TO_REASON(tag);
4190 }
4191 
4192 // TODO: remove this shim function and exported symbol
4193 IOReturn
changePowerStateTo(unsigned long ordinal)4194 IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
4195 {
4196 	return changePowerStateWithTagTo(ordinal, kCPSReasonNone);
4197 }
4198 
4199 // TODO: remove this shim function and exported symbol
4200 IOReturn
changePowerStateToPriv(unsigned long ordinal)4201 IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
4202 {
4203 	return changePowerStateWithTagToPriv(ordinal, kCPSReasonNone);
4204 }
4205 
4206 IOReturn
changePowerStateWithOverrideTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4207 IOPMrootDomain::changePowerStateWithOverrideTo(
4208 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4209 {
4210 	uint32_t tag = nextRequestTag(reason);
4211 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4212 
4213 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4214 		return kIOReturnUnsupported;
4215 	}
4216 
4217 	return super::changePowerStateWithOverrideTo(ordinal, tag);
4218 }
4219 
4220 IOReturn
changePowerStateWithTagTo(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4221 IOPMrootDomain::changePowerStateWithTagTo(
4222 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4223 {
4224 	uint32_t tag = nextRequestTag(reason);
4225 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4226 
4227 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4228 		return kIOReturnUnsupported;
4229 	}
4230 
4231 	return super::changePowerStateWithTagTo(ordinal, tag);
4232 }
4233 
4234 IOReturn
changePowerStateWithTagToPriv(IOPMPowerStateIndex ordinal,IOPMRequestTag reason)4235 IOPMrootDomain::changePowerStateWithTagToPriv(
4236 	IOPMPowerStateIndex ordinal, IOPMRequestTag reason )
4237 {
4238 	uint32_t tag = nextRequestTag(reason);
4239 	DLOG("%s(%s, %x)\n", __FUNCTION__, getPowerStateString((uint32_t) ordinal), tag);
4240 
4241 	if ((ordinal != ON_STATE) && (ordinal != AOT_STATE) && (ordinal != SLEEP_STATE)) {
4242 		return kIOReturnUnsupported;
4243 	}
4244 
4245 	return super::changePowerStateWithTagToPriv(ordinal, tag);
4246 }
4247 
4248 //******************************************************************************
4249 // activity detect
4250 //
4251 //******************************************************************************
4252 
4253 bool
activitySinceSleep(void)4254 IOPMrootDomain::activitySinceSleep(void)
4255 {
4256 	return userActivityCount != userActivityAtSleep;
4257 }
4258 
4259 bool
abortHibernation(void)4260 IOPMrootDomain::abortHibernation(void)
4261 {
4262 #if __arm64__
4263 	// don't allow hibernation to be aborted on ARM due to user activity
4264 	// since once ApplePMGR decides we're hibernating, we can't turn back
4265 	// see: <rdar://problem/63848862> Tonga ApplePMGR diff quiesce path support
4266 	return false;
4267 #else
4268 	bool ret = activitySinceSleep();
4269 
4270 	if (ret && !hibernateAborted && checkSystemCanSustainFullWake()) {
4271 		DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4272 		hibernateAborted = true;
4273 	}
4274 	return ret;
4275 #endif
4276 }
4277 
4278 extern "C" int
hibernate_should_abort(void)4279 hibernate_should_abort(void)
4280 {
4281 	if (gRootDomain) {
4282 		return gRootDomain->abortHibernation();
4283 	} else {
4284 		return 0;
4285 	}
4286 }
4287 
4288 //******************************************************************************
4289 // scheduleImmediateDebugWake
4290 //
4291 // Schedule a wake with RTC to wake us back up immediately after we sleep.
4292 // Useful when a cancel request comes in past the revert point on the sleep path
4293 //******************************************************************************
4294 
4295 void
scheduleImmediateDebugWake(void)4296 IOPMrootDomain::scheduleImmediateDebugWake( void )
4297 {
4298 	OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(1);
4299 	OSSharedPtr<OSNumber> secs = OSNumber::withNumber(1, 32);
4300 
4301 	if (dict && secs) {
4302 		dict->setObject(gIOPMSettingDebugWakeRelativeKey.get(), secs.get());
4303 		gRootDomain->setProperties(dict.get());
4304 		MSG("Reverting sleep with relative wake\n");
4305 	}
4306 }
4307 
4308 //******************************************************************************
4309 // willNotifyInterest
4310 //
4311 // Called after all priority clients have all acknowledged the power change,
4312 // but before any interested drivers and any power children are informed.
4313 // Dispatched though a thread call, so it is safe to perform work that might block on a
4314 // sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
4315 //******************************************************************************
4316 
4317 void
willNotifyInterested(IOPMPowerStateIndex newPowerState)4318 IOPMrootDomain::willNotifyInterested( IOPMPowerStateIndex newPowerState )
4319 {
4320 	if (SLEEP_STATE == newPowerState) {
4321 		_aotReadyToFullWake = false;
4322 #if 0
4323 		if (_aotLingerTime) {
4324 			uint64_t interval, deadline;
4325 			IOLog("aot linger no return\n");
4326 			nanoseconds_to_absolutetime(_aotLingerTime * NSEC_PER_MSEC, &interval);
4327 			clock_absolutetime_interval_to_deadline(interval, &deadline);
4328 			clock_delay_until(deadline);
4329 		}
4330 #endif
4331 		if (!_aotMode) {
4332 			_aotTestTime = 0;
4333 			_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
4334 			_aotLastWakeTime = 0;
4335 			if (_aotMetrics) {
4336 				bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4337 			}
4338 		} else if (!_aotNow && !_debugWakeSeconds) {
4339 			_aotNow            = true;
4340 			_aotPendingFlags   = 0;
4341 			_aotTasksSuspended = true;
4342 			_aotLastWakeTime   = 0;
4343 			bzero(_aotMetrics, sizeof(IOPMAOTMetrics));
4344 			if (kIOPMAOTModeCycle & _aotMode) {
4345 				clock_interval_to_absolutetime_interval(10, kSecondScale, &_aotTestInterval);
4346 				_aotTestTime = mach_continuous_time() + _aotTestInterval;
4347 				AbsoluteTime endInterval;
4348 				clock_interval_to_absolutetime_interval(60, kSecondScale, &endInterval);
4349 				_aotEndTime = mach_continuous_time() + endInterval;
4350 				_setWakeTime(_aotTestTime);
4351 			}
4352 			clock_interval_to_absolutetime_interval(2000, kMillisecondScale, &_aotWakePreWindow);
4353 			clock_interval_to_absolutetime_interval(1100, kMillisecondScale, &_aotWakePostWindow);
4354 		}
4355 
4356 		if (updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange)) {
4357 			IOLog("PMRD: tasks suspend\n");
4358 			AbsoluteTime deadline;
4359 
4360 			clock_interval_to_deadline(10, kSecondScale, &deadline);
4361 #if defined(XNU_TARGET_OS_OSX)
4362 			vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
4363 #endif /* defined(XNU_TARGET_OS_OSX) */
4364 		}
4365 	}
4366 }
4367 
4368 //******************************************************************************
4369 // willNotifyPowerChildren
4370 //
4371 // Called after all interested drivers have all acknowledged the power change,
4372 // but before any power children are informed.
4373 // Dispatched though a thread call, so it is safe to perform work that might block on a
4374 // sleeping disk. PM state machine (not thread) will block w/o timeout until this function returns.
4375 //******************************************************************************
4376 
4377 void
willNotifyPowerChildren(IOPMPowerStateIndex newPowerState)4378 IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
4379 {
4380 	if (SLEEP_STATE == newPowerState) {
4381 		notifierThread = current_thread();
4382 
4383 #if HIBERNATION
4384 		// Adjust watchdog for IOHibernateSystemSleep
4385 		int defaultTimeout = getWatchdogTimeout();
4386 		int timeout = defaultTimeout > WATCHDOG_HIBERNATION_TIMEOUT ?
4387 		    defaultTimeout : WATCHDOG_HIBERNATION_TIMEOUT;
4388 		reset_watchdog_timer(timeout);
4389 
4390 		IOHibernateSystemSleep();
4391 		IOHibernateIOKitSleep();
4392 #endif
4393 #if defined(__arm64__) && HIBERNATION
4394 		if (gIOHibernateState == kIOHibernateStateInactive) {
4395 			setProperty(kIOPMSystemSleepTypeKey, kIOPMSleepTypeDeepIdle, 32);
4396 		}
4397 		// On AS, hibernation cannot be aborted. Resetting RTC to 1s during hibernation upon detecting
4398 		// user activity is pointless (we are likely to spend >1s hibernating). It also clears existing
4399 		// alarms, which can mess with cycler tools.
4400 		if (gRootDomain->activitySinceSleep() && gIOHibernateState == kIOHibernateStateInactive) {
4401 #else /* defined(__arm64__) && HIBERNATION */
4402 		// On non-AS, hibernation can be aborted if user activity is detected. So continue to reset the
4403 		// RTC alarm (even during hibernation) so we can immediately wake from regular S2R if needed.
4404 		if (gRootDomain->activitySinceSleep()) {
4405 #endif /* defined(__arm64__) && HIBERNATION */
4406 			scheduleImmediateDebugWake();
4407 		}
4408 
4409 		notifierThread = NULL;
4410 	}
4411 }
4412 
4413 //******************************************************************************
4414 // willTellSystemCapabilityDidChange
4415 //
4416 // IOServicePM calls this from OurChangeTellCapabilityDidChange() when root
4417 // domain is raising its power state, immediately after notifying interested
4418 // drivers and power children.
4419 //******************************************************************************
4420 
4421 void
4422 IOPMrootDomain::willTellSystemCapabilityDidChange( void )
4423 {
4424 	if ((_systemTransitionType == kSystemTransitionWake) &&
4425 	    !CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
4426 		// After powering up drivers, dark->full promotion on the current wake
4427 		// transition is no longer possible. That is because the next machine
4428 		// state will issue the system capability change messages.
4429 		// The darkWakePowerClamped flag may already be set if the system has
4430 		// at least one driver that was power clamped due to dark wake.
4431 		// This function sets the darkWakePowerClamped flag in case there
4432 		// is no power-clamped driver in the system.
4433 		//
4434 		// Last opportunity to exit dark wake using:
4435 		// requestFullWake( kFullWakeReasonLocalUser );
4436 
4437 		if (!darkWakePowerClamped) {
4438 			if (darkWakeLogClamp) {
4439 				AbsoluteTime    now;
4440 				uint64_t        nsec;
4441 
4442 				clock_get_uptime(&now);
4443 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
4444 				absolutetime_to_nanoseconds(now, &nsec);
4445 				DLOG("dark wake promotion disabled at %u ms\n",
4446 				    ((int)((nsec) / NSEC_PER_MSEC)));
4447 			}
4448 			darkWakePowerClamped = true;
4449 		}
4450 	}
4451 }
4452 
4453 //******************************************************************************
4454 // sleepOnClamshellClosed
4455 //
4456 // contains the logic to determine if the system should sleep when the clamshell
4457 // is closed.
4458 //******************************************************************************
4459 
4460 bool
4461 IOPMrootDomain::shouldSleepOnClamshellClosed( void )
4462 {
4463 	if (!clamshellExists) {
4464 		return false;
4465 	}
4466 
4467 	DLOG("clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4468 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4469 
4470 	return !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisableMask;
4471 }
4472 
4473 bool
4474 IOPMrootDomain::shouldSleepOnRTCAlarmWake( void )
4475 {
4476 	// Called once every RTC/Alarm wake. Device should go to sleep if on clamshell
4477 	// closed && battery
4478 	if (!clamshellExists) {
4479 		return false;
4480 	}
4481 
4482 	DLOG("shouldSleepOnRTCAlarmWake: clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
4483 	    clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
4484 
4485 	return !acAdaptorConnected && !clamshellSleepDisableMask;
4486 }
4487 
4488 void
4489 IOPMrootDomain::sendClientClamshellNotification( void )
4490 {
4491 	/* Only broadcast clamshell alert if clamshell exists. */
4492 	if (!clamshellExists) {
4493 		return;
4494 	}
4495 
4496 	setProperty(kAppleClamshellStateKey,
4497 	    clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
4498 
4499 	setProperty(kAppleClamshellCausesSleepKey,
4500 	    shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
4501 
4502 	/* Argument to message is a bitfiel of
4503 	 *      ( kClamshellStateBit | kClamshellSleepBit )
4504 	 */
4505 	messageClients(kIOPMMessageClamshellStateChange,
4506 	    (void *)(uintptr_t) ((clamshellClosed ? kClamshellStateBit : 0)
4507 	    | (shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)));
4508 }
4509 
4510 //******************************************************************************
4511 // getSleepSupported
4512 //
4513 // Deprecated
4514 //******************************************************************************
4515 
4516 IOOptionBits
4517 IOPMrootDomain::getSleepSupported( void )
4518 {
4519 	return platformSleepSupport;
4520 }
4521 
4522 //******************************************************************************
4523 // setSleepSupported
4524 //
4525 // Deprecated
4526 //******************************************************************************
4527 
4528 void
4529 IOPMrootDomain::setSleepSupported( IOOptionBits flags )
4530 {
4531 	DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
4532 	OSBitOrAtomic(flags, &platformSleepSupport);
4533 }
4534 
4535 //******************************************************************************
4536 // setClamShellSleepDisable
4537 //
4538 //******************************************************************************
4539 
4540 void
4541 IOPMrootDomain::setClamShellSleepDisable( bool disable, uint32_t bitmask )
4542 {
4543 	uint32_t oldMask;
4544 
4545 	// User client calls this in non-gated context
4546 	if (gIOPMWorkLoop->inGate() == false) {
4547 		gIOPMWorkLoop->runAction(
4548 			OSMemberFunctionCast(IOWorkLoop::Action, this,
4549 			&IOPMrootDomain::setClamShellSleepDisable),
4550 			(OSObject *) this,
4551 			(void *) disable, (void *)(uintptr_t) bitmask);
4552 		return;
4553 	}
4554 
4555 	oldMask = clamshellSleepDisableMask;
4556 	if (disable) {
4557 		clamshellSleepDisableMask |= bitmask;
4558 	} else {
4559 		clamshellSleepDisableMask &= ~bitmask;
4560 	}
4561 	DLOG("setClamShellSleepDisable(%x->%x)\n", oldMask, clamshellSleepDisableMask);
4562 
4563 	if (clamshellExists && clamshellClosed &&
4564 	    (clamshellSleepDisableMask != oldMask) &&
4565 	    (clamshellSleepDisableMask == 0)) {
4566 		handlePowerNotification(kLocalEvalClamshellCommand);
4567 	}
4568 }
4569 
4570 //******************************************************************************
4571 // wakeFromDoze
4572 //
4573 // Deprecated.
4574 //******************************************************************************
4575 
4576 void
4577 IOPMrootDomain::wakeFromDoze( void )
4578 {
4579 	// Preserve symbol for familes (IOUSBFamily and IOGraphics)
4580 }
4581 
4582 //******************************************************************************
4583 // recordRTCAlarm
4584 //
4585 // Record the earliest scheduled RTC alarm to determine whether a RTC wake
4586 // should be a dark wake or a full wake. Both Maintenance and SleepService
4587 // alarms are dark wake, while AutoWake (WakeByCalendarDate) and DebugWake
4588 // (WakeRelativeToSleep) should trigger a full wake. Scheduled power-on
4589 // PMSettings are ignored.
4590 //
4591 // Caller serialized using settingsCtrlLock.
4592 //******************************************************************************
4593 
4594 void
4595 IOPMrootDomain::recordRTCAlarm(
4596 	const OSSymbol  *type,
4597 	OSObject        *object )
4598 {
4599 	uint32_t previousAlarmMask = _scheduledAlarmMask;
4600 
4601 	if (type == gIOPMSettingDebugWakeRelativeKey) {
4602 		OSNumber * n = OSDynamicCast(OSNumber, object);
4603 		if (n) {
4604 			// Debug wake has highest scheduling priority so it overrides any
4605 			// pre-existing alarm.
4606 			uint32_t debugSecs = n->unsigned32BitValue();
4607 			_nextScheduledAlarmType.reset(type, OSRetain);
4608 			_nextScheduledAlarmUTC = debugSecs;
4609 
4610 			_debugWakeSeconds = debugSecs;
4611 			OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarmMask);
4612 			DLOG("next alarm (%s) in %u secs\n",
4613 			    type->getCStringNoCopy(), debugSecs);
4614 		}
4615 	} else if ((type == gIOPMSettingAutoWakeCalendarKey.get()) ||
4616 	    (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) ||
4617 	    (type == gIOPMSettingSleepServiceWakeCalendarKey.get())) {
4618 		OSData * data = OSDynamicCast(OSData, object);
4619 		if (data && (data->getLength() == sizeof(IOPMCalendarStruct))) {
4620 			const IOPMCalendarStruct * cs;
4621 			bool replaceNextAlarm = false;
4622 			clock_sec_t secs;
4623 
4624 			cs = (const IOPMCalendarStruct *) data->getBytesNoCopy();
4625 			secs = IOPMConvertCalendarToSeconds(cs);
4626 			DLOG("%s " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4627 
4628 			// Update the next scheduled alarm type
4629 			if ((_nextScheduledAlarmType == NULL) ||
4630 			    ((_nextScheduledAlarmType != gIOPMSettingDebugWakeRelativeKey) &&
4631 			    (secs < _nextScheduledAlarmUTC))) {
4632 				replaceNextAlarm = true;
4633 			}
4634 
4635 			if (type == gIOPMSettingAutoWakeCalendarKey.get()) {
4636 				if (cs->year) {
4637 					_calendarWakeAlarmUTC = IOPMConvertCalendarToSeconds(cs);
4638 					OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4639 				} else {
4640 					// TODO: can this else-block be removed?
4641 					_calendarWakeAlarmUTC = 0;
4642 					OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarmMask);
4643 				}
4644 			}
4645 			if (type == gIOPMSettingMaintenanceWakeCalendarKey.get()) {
4646 				OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarmMask);
4647 			}
4648 			if (type == gIOPMSettingSleepServiceWakeCalendarKey.get()) {
4649 				OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarmMask);
4650 			}
4651 
4652 			if (replaceNextAlarm) {
4653 				_nextScheduledAlarmType.reset(type, OSRetain);
4654 				_nextScheduledAlarmUTC = secs;
4655 				DLOG("next alarm (%s) " YMDTF "\n", type->getCStringNoCopy(), YMDT(cs));
4656 			}
4657 		}
4658 	}
4659 
4660 	if (_scheduledAlarmMask != previousAlarmMask) {
4661 		DLOG("scheduled alarm mask 0x%x\n", (uint32_t) _scheduledAlarmMask);
4662 	}
4663 }
4664 
4665 // MARK: -
4666 // MARK: Features
4667 
4668 //******************************************************************************
4669 // publishFeature
4670 //
4671 // Adds a new feature to the supported features dictionary
4672 //******************************************************************************
4673 
4674 void
4675 IOPMrootDomain::publishFeature( const char * feature )
4676 {
4677 	publishFeature(feature, kRD_AllPowerSources, NULL);
4678 }
4679 
4680 //******************************************************************************
4681 // publishFeature (with supported power source specified)
4682 //
4683 // Adds a new feature to the supported features dictionary
4684 //******************************************************************************
4685 
4686 void
4687 IOPMrootDomain::publishFeature(
4688 	const char *feature,
4689 	uint32_t supportedWhere,
4690 	uint32_t *uniqueFeatureID)
4691 {
4692 	static uint16_t       next_feature_id = 500;
4693 
4694 	OSSharedPtr<OSNumber> new_feature_data;
4695 	OSNumber             *existing_feature = NULL;
4696 	OSArray              *existing_feature_arr_raw = NULL;
4697 	OSSharedPtr<OSArray>  existing_feature_arr;
4698 	OSObject             *osObj = NULL;
4699 	uint32_t              feature_value = 0;
4700 
4701 	supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
4702 
4703 	if (!supportedWhere) {
4704 		// Feature isn't supported anywhere!
4705 		return;
4706 	}
4707 
4708 	if (next_feature_id > 5000) {
4709 		// Far, far too many features!
4710 		return;
4711 	}
4712 
4713 	if (featuresDictLock) {
4714 		IOLockLock(featuresDictLock);
4715 	}
4716 
4717 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4718 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4719 	OSSharedPtr<OSDictionary> features;
4720 
4721 	// Create new features dict if necessary
4722 	if (origFeatures) {
4723 		features = OSDictionary::withDictionary(origFeatures);
4724 	} else {
4725 		features = OSDictionary::withCapacity(1);
4726 	}
4727 
4728 	// Create OSNumber to track new feature
4729 
4730 	next_feature_id += 1;
4731 	if (uniqueFeatureID) {
4732 		// We don't really mind if the calling kext didn't give us a place
4733 		// to stash their unique id. Many kexts don't plan to unload, and thus
4734 		// have no need to remove themselves later.
4735 		*uniqueFeatureID = next_feature_id;
4736 	}
4737 
4738 	feature_value = (uint32_t)next_feature_id;
4739 	feature_value <<= 16;
4740 	feature_value += supportedWhere;
4741 
4742 	new_feature_data = OSNumber::withNumber(
4743 		(unsigned long long)feature_value, 32);
4744 
4745 	// Does features object already exist?
4746 	if ((osObj = features->getObject(feature))) {
4747 		if ((existing_feature = OSDynamicCast(OSNumber, osObj))) {
4748 			// We need to create an OSArray to hold the now 2 elements.
4749 			existing_feature_arr = OSArray::withObjects(
4750 				(const OSObject **)&existing_feature, 1, 2);
4751 		} else if ((existing_feature_arr_raw = OSDynamicCast(OSArray, osObj))) {
4752 			// Add object to existing array
4753 			existing_feature_arr = OSArray::withArray(
4754 				existing_feature_arr_raw,
4755 				existing_feature_arr_raw->getCount() + 1);
4756 		}
4757 
4758 		if (existing_feature_arr) {
4759 			existing_feature_arr->setObject(new_feature_data.get());
4760 			features->setObject(feature, existing_feature_arr.get());
4761 		}
4762 	} else {
4763 		// The easy case: no previously existing features listed. We simply
4764 		// set the OSNumber at key 'feature' and we're on our way.
4765 		features->setObject(feature, new_feature_data.get());
4766 	}
4767 
4768 	setProperty(kRootDomainSupportedFeatures, features.get());
4769 
4770 	if (featuresDictLock) {
4771 		IOLockUnlock(featuresDictLock);
4772 	}
4773 
4774 	// Notify EnergySaver and all those in user space so they might
4775 	// re-populate their feature specific UI
4776 	if (pmPowerStateQueue) {
4777 		pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4778 	}
4779 }
4780 
4781 //******************************************************************************
4782 // removePublishedFeature
4783 //
4784 // Removes previously published feature
4785 //******************************************************************************
4786 
4787 IOReturn
4788 IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
4789 {
4790 	IOReturn                ret = kIOReturnError;
4791 	uint32_t                feature_value = 0;
4792 	uint16_t                feature_id = 0;
4793 	bool                    madeAChange = false;
4794 
4795 	OSSymbol                *dictKey = NULL;
4796 	OSSharedPtr<OSCollectionIterator>    dictIterator;
4797 	OSArray                 *arrayMember  = NULL;
4798 	OSNumber                *numberMember = NULL;
4799 	OSObject                *osObj        = NULL;
4800 	OSNumber                *osNum        = NULL;
4801 	OSSharedPtr<OSArray>    arrayMemberCopy;
4802 
4803 	if (kBadPMFeatureID == removeFeatureID) {
4804 		return kIOReturnNotFound;
4805 	}
4806 
4807 	if (featuresDictLock) {
4808 		IOLockLock(featuresDictLock);
4809 	}
4810 
4811 	OSSharedPtr<OSObject> origFeaturesProp = copyProperty(kRootDomainSupportedFeatures);
4812 	OSDictionary *origFeatures = OSDynamicCast(OSDictionary, origFeaturesProp.get());
4813 	OSSharedPtr<OSDictionary> features;
4814 
4815 	if (origFeatures) {
4816 		// Any modifications to the dictionary are made to the copy to prevent
4817 		// races & crashes with userland clients. Dictionary updated
4818 		// automically later.
4819 		features = OSDictionary::withDictionary(origFeatures);
4820 	} else {
4821 		features = NULL;
4822 		ret = kIOReturnNotFound;
4823 		goto exit;
4824 	}
4825 
4826 	// We iterate 'features' dictionary looking for an entry tagged
4827 	// with 'removeFeatureID'. If found, we remove it from our tracking
4828 	// structures and notify the OS via a general interest message.
4829 
4830 	dictIterator = OSCollectionIterator::withCollection(features.get());
4831 	if (!dictIterator) {
4832 		goto exit;
4833 	}
4834 
4835 	while ((dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject()))) {
4836 		osObj = features->getObject(dictKey);
4837 
4838 		// Each Feature is either tracked by an OSNumber
4839 		if (osObj && (numberMember = OSDynamicCast(OSNumber, osObj))) {
4840 			feature_value = numberMember->unsigned32BitValue();
4841 			feature_id = (uint16_t)(feature_value >> 16);
4842 
4843 			if (feature_id == (uint16_t)removeFeatureID) {
4844 				// Remove this node
4845 				features->removeObject(dictKey);
4846 				madeAChange = true;
4847 				break;
4848 			}
4849 
4850 			// Or tracked by an OSArray of OSNumbers
4851 		} else if (osObj && (arrayMember = OSDynamicCast(OSArray, osObj))) {
4852 			unsigned int arrayCount = arrayMember->getCount();
4853 
4854 			for (unsigned int i = 0; i < arrayCount; i++) {
4855 				osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
4856 				if (!osNum) {
4857 					continue;
4858 				}
4859 
4860 				feature_value = osNum->unsigned32BitValue();
4861 				feature_id = (uint16_t)(feature_value >> 16);
4862 
4863 				if (feature_id == (uint16_t)removeFeatureID) {
4864 					// Remove this node
4865 					if (1 == arrayCount) {
4866 						// If the array only contains one element, remove
4867 						// the whole thing.
4868 						features->removeObject(dictKey);
4869 					} else {
4870 						// Otherwise remove the element from a copy of the array.
4871 						arrayMemberCopy = OSArray::withArray(arrayMember);
4872 						if (arrayMemberCopy) {
4873 							arrayMemberCopy->removeObject(i);
4874 							features->setObject(dictKey, arrayMemberCopy.get());
4875 						}
4876 					}
4877 
4878 					madeAChange = true;
4879 					break;
4880 				}
4881 			}
4882 		}
4883 	}
4884 
4885 	if (madeAChange) {
4886 		ret = kIOReturnSuccess;
4887 
4888 		setProperty(kRootDomainSupportedFeatures, features.get());
4889 
4890 		// Notify EnergySaver and all those in user space so they might
4891 		// re-populate their feature specific UI
4892 		if (pmPowerStateQueue) {
4893 			pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
4894 		}
4895 	} else {
4896 		ret = kIOReturnNotFound;
4897 	}
4898 
4899 exit:
4900 	if (featuresDictLock) {
4901 		IOLockUnlock(featuresDictLock);
4902 	}
4903 	return ret;
4904 }
4905 
4906 //******************************************************************************
4907 // publishPMSetting (private)
4908 //
4909 // Should only be called by PMSettingObject to publish a PM Setting as a
4910 // supported feature.
4911 //******************************************************************************
4912 
4913 void
4914 IOPMrootDomain::publishPMSetting(
4915 	const OSSymbol * feature, uint32_t where, uint32_t * featureID )
4916 {
4917 	if (noPublishPMSettings &&
4918 	    (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1)) {
4919 		// Setting found in noPublishPMSettings array
4920 		*featureID = kBadPMFeatureID;
4921 		return;
4922 	}
4923 
4924 	publishFeature(
4925 		feature->getCStringNoCopy(), where, featureID);
4926 }
4927 
4928 //******************************************************************************
4929 // setPMSetting (private)
4930 //
4931 // Internal helper to relay PM settings changes from user space to individual
4932 // drivers. Should be called only by IOPMrootDomain::setProperties.
4933 //******************************************************************************
4934 
4935 IOReturn
4936 IOPMrootDomain::setPMSetting(
4937 	const OSSymbol  *type,
4938 	OSObject        *object )
4939 {
4940 	PMSettingCallEntry  *entries = NULL;
4941 	OSSharedPtr<OSArray>    chosen;
4942 	const OSArray       *array;
4943 	PMSettingObject     *pmso;
4944 	thread_t            thisThread;
4945 	int                 i, j, count, capacity;
4946 	bool                ok = false;
4947 	IOReturn            ret;
4948 
4949 	if (NULL == type) {
4950 		return kIOReturnBadArgument;
4951 	}
4952 
4953 	PMSETTING_LOCK();
4954 
4955 	// Update settings dict so changes are visible from copyPMSetting().
4956 	fPMSettingsDict->setObject(type, object);
4957 
4958 	// Prep all PMSetting objects with the given 'type' for callout.
4959 	array = OSDynamicCast(OSArray, settingsCallbacks->getObject(type));
4960 	if (!array || ((capacity = array->getCount()) == 0)) {
4961 		goto unlock_exit;
4962 	}
4963 
4964 	// Array to retain PMSetting objects targeted for callout.
4965 	chosen = OSArray::withCapacity(capacity);
4966 	if (!chosen) {
4967 		goto unlock_exit; // error
4968 	}
4969 	entries = IONew(PMSettingCallEntry, capacity);
4970 	if (!entries) {
4971 		goto unlock_exit; // error
4972 	}
4973 	memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
4974 
4975 	thisThread = current_thread();
4976 
4977 	for (i = 0, j = 0; i < capacity; i++) {
4978 		pmso = (PMSettingObject *) array->getObject(i);
4979 		if (pmso->disabled) {
4980 			continue;
4981 		}
4982 		entries[j].thread = thisThread;
4983 		queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
4984 		chosen->setObject(pmso);
4985 		j++;
4986 	}
4987 	count = j;
4988 	if (!count) {
4989 		goto unlock_exit;
4990 	}
4991 
4992 	PMSETTING_UNLOCK();
4993 
4994 	// Call each pmso in the chosen array.
4995 	for (i = 0; i < count; i++) {
4996 		pmso = (PMSettingObject *) chosen->getObject(i);
4997 		ret = pmso->dispatchPMSetting(type, object);
4998 		if (ret == kIOReturnSuccess) {
4999 			// At least one setting handler was successful
5000 			ok = true;
5001 #if DEVELOPMENT || DEBUG
5002 		} else {
5003 			// Log the handler and kext that failed
5004 			OSSharedPtr<const OSSymbol> kextName = copyKextIdentifierWithAddress((vm_address_t) pmso->func);
5005 			if (kextName) {
5006 				DLOG("PMSetting(%s) error 0x%x from %s\n",
5007 				    type->getCStringNoCopy(), ret, kextName->getCStringNoCopy());
5008 			}
5009 #endif
5010 		}
5011 	}
5012 
5013 	PMSETTING_LOCK();
5014 	for (i = 0; i < count; i++) {
5015 		pmso = (PMSettingObject *) chosen->getObject(i);
5016 		queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
5017 		if (pmso->waitThread) {
5018 			PMSETTING_WAKEUP(pmso);
5019 		}
5020 	}
5021 
5022 	if (ok) {
5023 		recordRTCAlarm(type, object);
5024 	}
5025 unlock_exit:
5026 	PMSETTING_UNLOCK();
5027 
5028 	if (entries) {
5029 		IODelete(entries, PMSettingCallEntry, capacity);
5030 	}
5031 
5032 	return kIOReturnSuccess;
5033 }
5034 
5035 //******************************************************************************
5036 // copyPMSetting (public)
5037 //
5038 // Allows kexts to safely read setting values, without being subscribed to
5039 // notifications.
5040 //******************************************************************************
5041 
5042 OSSharedPtr<OSObject>
5043 IOPMrootDomain::copyPMSetting(
5044 	OSSymbol *whichSetting)
5045 {
5046 	OSSharedPtr<OSObject> obj;
5047 
5048 	if (!whichSetting) {
5049 		return NULL;
5050 	}
5051 
5052 	PMSETTING_LOCK();
5053 	obj.reset(fPMSettingsDict->getObject(whichSetting), OSRetain);
5054 	PMSETTING_UNLOCK();
5055 
5056 	return obj;
5057 }
5058 
5059 //******************************************************************************
5060 // registerPMSettingController (public)
5061 //
5062 // direct wrapper to registerPMSettingController with uint32_t power source arg
5063 //******************************************************************************
5064 
5065 IOReturn
5066 IOPMrootDomain::registerPMSettingController(
5067 	const OSSymbol *                settings[],
5068 	IOPMSettingControllerCallback   func,
5069 	OSObject                        *target,
5070 	uintptr_t                       refcon,
5071 	OSObject                        **handle)
5072 {
5073 	return registerPMSettingController(
5074 		settings,
5075 		(kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
5076 		func, target, refcon, handle);
5077 }
5078 
5079 //******************************************************************************
5080 // registerPMSettingController (public)
5081 //
5082 // Kexts may register for notifications when a particular setting is changed.
5083 // A list of settings is available in IOPM.h.
5084 // Arguments:
5085 //  * settings - An OSArray containing OSSymbols. Caller should populate this
5086 //          array with a list of settings caller wants notifications from.
5087 //  * func - A C function callback of the type IOPMSettingControllerCallback
5088 //  * target - caller may provide an OSObject *, which PM will pass as an
5089 //          target to calls to "func"
5090 //  * refcon - caller may provide an void *, which PM will pass as an
5091 //          argument to calls to "func"
5092 //  * handle - This is a return argument. We will populate this pointer upon
5093 //          call success. Hold onto this and pass this argument to
5094 //          IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
5095 // Returns:
5096 //      kIOReturnSuccess on success
5097 //******************************************************************************
5098 
5099 IOReturn
5100 IOPMrootDomain::registerPMSettingController(
5101 	const OSSymbol *                settings[],
5102 	uint32_t                        supportedPowerSources,
5103 	IOPMSettingControllerCallback   func,
5104 	OSObject                        *target,
5105 	uintptr_t                       refcon,
5106 	OSObject                        **handle)
5107 {
5108 	PMSettingObject *pmso = NULL;
5109 	OSObject        *pmsh = NULL;
5110 	int             i;
5111 
5112 	if (NULL == settings ||
5113 	    NULL == func ||
5114 	    NULL == handle) {
5115 		return kIOReturnBadArgument;
5116 	}
5117 
5118 	pmso = PMSettingObject::pmSettingObject(
5119 		(IOPMrootDomain *) this, func, target,
5120 		refcon, supportedPowerSources, settings, &pmsh);
5121 
5122 	if (!pmso) {
5123 		*handle = NULL;
5124 		return kIOReturnInternalError;
5125 	}
5126 
5127 	PMSETTING_LOCK();
5128 	for (i = 0; settings[i]; i++) {
5129 		OSSharedPtr<OSArray> newList;
5130 		OSArray *list = OSDynamicCast(OSArray, settingsCallbacks->getObject(settings[i]));
5131 		if (!list) {
5132 			// New array of callbacks for this setting
5133 			newList = OSArray::withCapacity(1);
5134 			settingsCallbacks->setObject(settings[i], newList.get());
5135 			list = newList.get();
5136 		}
5137 
5138 		// Add caller to the callback list
5139 		list->setObject(pmso);
5140 	}
5141 	PMSETTING_UNLOCK();
5142 
5143 	// Return handle to the caller, the setting object is private.
5144 	*handle = pmsh;
5145 
5146 	return kIOReturnSuccess;
5147 }
5148 
5149 //******************************************************************************
5150 // deregisterPMSettingObject (private)
5151 //
5152 // Only called from PMSettingObject.
5153 //******************************************************************************
5154 
5155 void
5156 IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
5157 {
5158 	thread_t                thisThread = current_thread();
5159 	PMSettingCallEntry      *callEntry;
5160 	OSSharedPtr<OSCollectionIterator>    iter;
5161 	OSSymbol                *sym;
5162 	OSArray                 *array;
5163 	int                     index;
5164 	bool                    wait;
5165 
5166 	PMSETTING_LOCK();
5167 
5168 	pmso->disabled = true;
5169 
5170 	// Wait for all callout threads to finish.
5171 	do {
5172 		wait = false;
5173 		queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
5174 		{
5175 			if (callEntry->thread != thisThread) {
5176 				wait = true;
5177 				break;
5178 			}
5179 		}
5180 		if (wait) {
5181 			assert(NULL == pmso->waitThread);
5182 			pmso->waitThread = thisThread;
5183 			PMSETTING_WAIT(pmso);
5184 			pmso->waitThread = NULL;
5185 		}
5186 	} while (wait);
5187 
5188 	// Search each PM settings array in the kernel.
5189 	iter = OSCollectionIterator::withCollection(settingsCallbacks.get());
5190 	if (iter) {
5191 		while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
5192 			array = OSDynamicCast(OSArray, settingsCallbacks->getObject(sym));
5193 			index = array->getNextIndexOfObject(pmso, 0);
5194 			if (-1 != index) {
5195 				array->removeObject(index);
5196 			}
5197 		}
5198 	}
5199 
5200 	PMSETTING_UNLOCK();
5201 
5202 	pmso->release();
5203 }
5204 
5205 //******************************************************************************
5206 // informCPUStateChange
5207 //
5208 // Call into PM CPU code so that CPU power savings may dynamically adjust for
5209 // running on battery, with the lid closed, etc.
5210 //
5211 // informCPUStateChange is a no-op on non x86 systems
5212 // only x86 has explicit support in the IntelCPUPowerManagement kext
5213 //******************************************************************************
5214 
5215 void
5216 IOPMrootDomain::informCPUStateChange(
5217 	uint32_t type,
5218 	uint32_t value )
5219 {
5220 #if defined(__i386__) || defined(__x86_64__)
5221 
5222 	pmioctlVariableInfo_t varInfoStruct;
5223 	int                 pmCPUret = 0;
5224 	const char          *varNameStr = NULL;
5225 	int32_t             *varIndex   = NULL;
5226 
5227 	if (kInformAC == type) {
5228 		varNameStr = kIOPMRootDomainBatPowerCString;
5229 		varIndex = &idxPMCPULimitedPower;
5230 	} else if (kInformLid == type) {
5231 		varNameStr = kIOPMRootDomainLidCloseCString;
5232 		varIndex = &idxPMCPUClamshell;
5233 	} else {
5234 		return;
5235 	}
5236 
5237 	// Set the new value!
5238 	// pmCPUControl will assign us a new ID if one doesn't exist yet
5239 	bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
5240 	varInfoStruct.varID         = *varIndex;
5241 	varInfoStruct.varType       = vBool;
5242 	varInfoStruct.varInitValue  = value;
5243 	varInfoStruct.varCurValue   = value;
5244 	strlcpy((char *)varInfoStruct.varName,
5245 	    (const char *)varNameStr,
5246 	    sizeof(varInfoStruct.varName));
5247 
5248 	// Set!
5249 	pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
5250 
5251 	// pmCPU only assigns numerical id's when a new varName is specified
5252 	if ((0 == pmCPUret)
5253 	    && (*varIndex == kCPUUnknownIndex)) {
5254 		// pmCPUControl has assigned us a new variable ID.
5255 		// Let's re-read the structure we just SET to learn that ID.
5256 		pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
5257 
5258 		if (0 == pmCPUret) {
5259 			// Store it in idxPMCPUClamshell or idxPMCPULimitedPower
5260 			*varIndex = varInfoStruct.varID;
5261 		}
5262 	}
5263 
5264 	return;
5265 
5266 #endif /* __i386__ || __x86_64__ */
5267 }
5268 
5269 // MARK: -
5270 // MARK: Deep Sleep Policy
5271 
5272 #if HIBERNATION
5273 
5274 //******************************************************************************
5275 // evaluateSystemSleepPolicy
5276 //******************************************************************************
5277 
5278 #define kIOPlatformSystemSleepPolicyKey     "IOPlatformSystemSleepPolicy"
5279 
5280 // Sleep flags
5281 enum {
5282 	kIOPMSleepFlagHibernate         = 0x00000001,
5283 	kIOPMSleepFlagSleepTimerEnable  = 0x00000002
5284 };
5285 
5286 struct IOPMSystemSleepPolicyEntry {
5287 	uint32_t    factorMask;
5288 	uint32_t    factorBits;
5289 	uint32_t    sleepFlags;
5290 	uint32_t    wakeEvents;
5291 } __attribute__((packed));
5292 
5293 struct IOPMSystemSleepPolicyTable {
5294 	uint32_t    signature;
5295 	uint16_t    version;
5296 	uint16_t    entryCount;
5297 	IOPMSystemSleepPolicyEntry  entries[];
5298 } __attribute__((packed));
5299 
5300 enum {
5301 	kIOPMSleepAttributeHibernateSetup   = 0x00000001,
5302 	kIOPMSleepAttributeHibernateSleep   = 0x00000002
5303 };
5304 
5305 static uint32_t
5306 getSleepTypeAttributes( uint32_t sleepType )
5307 {
5308 	static const uint32_t sleepTypeAttributes[kIOPMSleepTypeLast] =
5309 	{
5310 		/* invalid   */ 0,
5311 		/* abort     */ 0,
5312 		/* normal    */ 0,
5313 		/* safesleep */ kIOPMSleepAttributeHibernateSetup,
5314 		/* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5315 		/* standby   */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5316 		/* poweroff  */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
5317 		/* deepidle  */ 0
5318 	};
5319 
5320 	if (sleepType >= kIOPMSleepTypeLast) {
5321 		return 0;
5322 	}
5323 
5324 	return sleepTypeAttributes[sleepType];
5325 }
5326 
5327 bool
5328 IOPMrootDomain::evaluateSystemSleepPolicy(
5329 	IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
5330 {
5331 #define SLEEP_FACTOR(x) {(uint32_t) kIOPMSleepFactor ## x, #x}
5332 
5333 	static const IONamedValue factorValues[] = {
5334 		SLEEP_FACTOR( SleepTimerWake ),
5335 		SLEEP_FACTOR( LidOpen ),
5336 		SLEEP_FACTOR( ACPower ),
5337 		SLEEP_FACTOR( BatteryLow ),
5338 		SLEEP_FACTOR( StandbyNoDelay ),
5339 		SLEEP_FACTOR( StandbyForced ),
5340 		SLEEP_FACTOR( StandbyDisabled ),
5341 		SLEEP_FACTOR( USBExternalDevice ),
5342 		SLEEP_FACTOR( BluetoothHIDDevice ),
5343 		SLEEP_FACTOR( ExternalMediaMounted ),
5344 		SLEEP_FACTOR( ThunderboltDevice ),
5345 		SLEEP_FACTOR( RTCAlarmScheduled ),
5346 		SLEEP_FACTOR( MagicPacketWakeEnabled ),
5347 		SLEEP_FACTOR( HibernateForced ),
5348 		SLEEP_FACTOR( AutoPowerOffDisabled ),
5349 		SLEEP_FACTOR( AutoPowerOffForced ),
5350 		SLEEP_FACTOR( ExternalDisplay ),
5351 		SLEEP_FACTOR( NetworkKeepAliveActive ),
5352 		SLEEP_FACTOR( LocalUserActivity ),
5353 		SLEEP_FACTOR( HibernateFailed ),
5354 		SLEEP_FACTOR( ThermalWarning ),
5355 		SLEEP_FACTOR( DisplayCaptured ),
5356 		{ 0, NULL }
5357 	};
5358 
5359 	const IOPMSystemSleepPolicyTable * pt;
5360 	OSSharedPtr<OSObject>  prop;
5361 	OSData *    policyData;
5362 	uint64_t    currentFactors = 0;
5363 	char        currentFactorsBuf[512];
5364 	uint32_t    standbyDelay   = 0;
5365 	uint32_t    powerOffDelay  = 0;
5366 	uint32_t    powerOffTimer  = 0;
5367 	uint32_t    standbyTimer  = 0;
5368 	uint32_t    mismatch;
5369 	bool        standbyEnabled;
5370 	bool        powerOffEnabled;
5371 	bool        found = false;
5372 
5373 	// Get platform's sleep policy table
5374 	if (!gSleepPolicyHandler) {
5375 		prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
5376 		if (!prop) {
5377 			goto done;
5378 		}
5379 	}
5380 
5381 	// Fetch additional settings
5382 	standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
5383 	    && propertyHasValue(kIOPMDeepSleepEnabledKey, kOSBooleanTrue));
5384 	powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
5385 	    && propertyHasValue(kIOPMAutoPowerOffEnabledKey, kOSBooleanTrue));
5386 	if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) {
5387 		powerOffTimer = powerOffDelay;
5388 	}
5389 	if (!getSleepOption(kIOPMDeepSleepTimerKey, &standbyTimer)) {
5390 		standbyTimer = standbyDelay;
5391 	}
5392 
5393 	DLOG("phase %d, standby %d delay %u timer %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
5394 	    sleepPhase, standbyEnabled, standbyDelay, standbyTimer,
5395 	    powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
5396 
5397 	currentFactorsBuf[0] = 0;
5398 	// pmset level overrides
5399 	if ((*hibMode & kIOHibernateModeOn) == 0) {
5400 		if (!gSleepPolicyHandler) {
5401 			standbyEnabled  = false;
5402 			powerOffEnabled = false;
5403 		}
5404 	} else if (!(*hibMode & kIOHibernateModeSleep)) {
5405 		// Force hibernate (i.e. mode 25)
5406 		// If standby is enabled, force standy.
5407 		// If poweroff is enabled, force poweroff.
5408 		if (standbyEnabled) {
5409 			currentFactors |= kIOPMSleepFactorStandbyForced;
5410 		} else if (powerOffEnabled) {
5411 			currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
5412 		} else {
5413 			currentFactors |= kIOPMSleepFactorHibernateForced;
5414 		}
5415 	}
5416 
5417 	// Current factors based on environment and assertions
5418 	if (sleepTimerMaintenance) {
5419 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5420 	}
5421 	if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler) {
5422 		currentFactors |= kIOPMSleepFactorSleepTimerWake;
5423 	}
5424 	if (!clamshellClosed) {
5425 		currentFactors |= kIOPMSleepFactorLidOpen;
5426 	}
5427 	if (acAdaptorConnected) {
5428 		currentFactors |= kIOPMSleepFactorACPower;
5429 	}
5430 	if (lowBatteryCondition) {
5431 		hibernateMode = 0;
5432 		getSleepOption(kIOHibernateModeKey, &hibernateMode);
5433 		if ((hibernateMode & kIOHibernateModeOn) == 0) {
5434 			DLOG("HibernateMode is 0. Not sending LowBattery factor to IOPPF\n");
5435 		} else {
5436 			currentFactors |= kIOPMSleepFactorBatteryLow;
5437 		}
5438 	}
5439 	if (!standbyDelay || !standbyTimer) {
5440 		currentFactors |= kIOPMSleepFactorStandbyNoDelay;
5441 	}
5442 	if (standbyNixed || !standbyEnabled) {
5443 		currentFactors |= kIOPMSleepFactorStandbyDisabled;
5444 	}
5445 	if (resetTimers) {
5446 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5447 		currentFactors &= ~kIOPMSleepFactorSleepTimerWake;
5448 	}
5449 	if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
5450 	    kIOPMDriverAssertionLevelOff) {
5451 		currentFactors |= kIOPMSleepFactorUSBExternalDevice;
5452 	}
5453 	if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
5454 	    kIOPMDriverAssertionLevelOff) {
5455 		currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
5456 	}
5457 	if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
5458 	    kIOPMDriverAssertionLevelOff) {
5459 		currentFactors |= kIOPMSleepFactorExternalMediaMounted;
5460 	}
5461 	if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
5462 	    kIOPMDriverAssertionLevelOff) {
5463 		currentFactors |= kIOPMSleepFactorThunderboltDevice;
5464 	}
5465 	if (_scheduledAlarmMask != 0) {
5466 		currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
5467 	}
5468 	if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
5469 	    kIOPMDriverAssertionLevelOff) {
5470 		currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
5471 	}
5472 #define TCPKEEPALIVE 1
5473 #if TCPKEEPALIVE
5474 	if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
5475 	    kIOPMDriverAssertionLevelOff) {
5476 		currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
5477 	}
5478 #endif
5479 	if (!powerOffEnabled) {
5480 		currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
5481 	}
5482 	if (desktopMode) {
5483 		currentFactors |= kIOPMSleepFactorExternalDisplay;
5484 	}
5485 	if (userWasActive) {
5486 		currentFactors |= kIOPMSleepFactorLocalUserActivity;
5487 	}
5488 	if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
5489 		currentFactors |= kIOPMSleepFactorHibernateFailed;
5490 	}
5491 	if (thermalWarningState) {
5492 		currentFactors |= kIOPMSleepFactorThermalWarning;
5493 	}
5494 
5495 	for (int factorBit = 0; factorBit < (8 * sizeof(uint32_t)); factorBit++) {
5496 		uint32_t factor = 1 << factorBit;
5497 		if (factor & currentFactors) {
5498 			strlcat(currentFactorsBuf, ", ", sizeof(currentFactorsBuf));
5499 			strlcat(currentFactorsBuf, IOFindNameForValue(factor, factorValues), sizeof(currentFactorsBuf));
5500 		}
5501 	}
5502 	DLOG("sleep factors 0x%llx%s\n", currentFactors, currentFactorsBuf);
5503 
5504 	if (gSleepPolicyHandler) {
5505 		uint32_t    savedHibernateMode;
5506 		IOReturn    result;
5507 
5508 		if (!gSleepPolicyVars) {
5509 			gSleepPolicyVars = IOMallocType(IOPMSystemSleepPolicyVariables);
5510 		}
5511 		gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
5512 		gSleepPolicyVars->version   = kIOPMSystemSleepPolicyVersion;
5513 		gSleepPolicyVars->currentCapability = _currentCapability;
5514 		gSleepPolicyVars->highestCapability = _highestCapability;
5515 		gSleepPolicyVars->sleepFactors      = currentFactors;
5516 		gSleepPolicyVars->sleepReason       = lastSleepReason;
5517 		gSleepPolicyVars->sleepPhase        = sleepPhase;
5518 		gSleepPolicyVars->standbyDelay      = standbyDelay;
5519 		gSleepPolicyVars->standbyTimer      = standbyTimer;
5520 		gSleepPolicyVars->poweroffDelay     = powerOffDelay;
5521 		gSleepPolicyVars->scheduledAlarms   = _scheduledAlarmMask | _userScheduledAlarmMask;
5522 		gSleepPolicyVars->poweroffTimer     = powerOffTimer;
5523 
5524 		if (kIOPMSleepPhase0 == sleepPhase) {
5525 			// preserve hibernateMode
5526 			savedHibernateMode = gSleepPolicyVars->hibernateMode;
5527 			gSleepPolicyVars->hibernateMode = *hibMode;
5528 		} else if (kIOPMSleepPhase1 == sleepPhase) {
5529 			// use original hibernateMode for phase2
5530 			gSleepPolicyVars->hibernateMode = *hibMode;
5531 		}
5532 
5533 		result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
5534 
5535 		if (kIOPMSleepPhase0 == sleepPhase) {
5536 			// restore hibernateMode
5537 			gSleepPolicyVars->hibernateMode = savedHibernateMode;
5538 		}
5539 
5540 		if ((result != kIOReturnSuccess) ||
5541 		    (kIOPMSleepTypeInvalid == params->sleepType) ||
5542 		    (params->sleepType >= kIOPMSleepTypeLast) ||
5543 		    (kIOPMSystemSleepParametersVersion != params->version)) {
5544 			MSG("sleep policy handler error\n");
5545 			goto done;
5546 		}
5547 
5548 		if ((getSleepTypeAttributes(params->sleepType) &
5549 		    kIOPMSleepAttributeHibernateSetup) &&
5550 		    ((*hibMode & kIOHibernateModeOn) == 0)) {
5551 			*hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
5552 		}
5553 
5554 		DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
5555 		    params->version, params->sleepType, params->sleepFlags,
5556 		    params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
5557 		found = true;
5558 		goto done;
5559 	}
5560 
5561 	// Policy table is meaningless without standby enabled
5562 	if (!standbyEnabled) {
5563 		goto done;
5564 	}
5565 
5566 	// Validate the sleep policy table
5567 	policyData = OSDynamicCast(OSData, prop.get());
5568 	if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable))) {
5569 		goto done;
5570 	}
5571 
5572 	pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
5573 	if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
5574 	    (pt->version != 1) || (0 == pt->entryCount)) {
5575 		goto done;
5576 	}
5577 
5578 	if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
5579 	    (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))) {
5580 		goto done;
5581 	}
5582 
5583 	for (uint32_t i = 0; i < pt->entryCount; i++) {
5584 		const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
5585 		mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
5586 
5587 		DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
5588 		    entry->factorMask, entry->factorBits,
5589 		    entry->sleepFlags, entry->wakeEvents, mismatch);
5590 		if (mismatch) {
5591 			continue;
5592 		}
5593 
5594 		DLOG("^ found match\n");
5595 		found = true;
5596 
5597 		params->version = kIOPMSystemSleepParametersVersion;
5598 		params->reserved1 = 1;
5599 		if (entry->sleepFlags & kIOPMSleepFlagHibernate) {
5600 			params->sleepType = kIOPMSleepTypeStandby;
5601 		} else {
5602 			params->sleepType = kIOPMSleepTypeNormalSleep;
5603 		}
5604 
5605 		params->ecWakeEvents = entry->wakeEvents;
5606 		if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable) {
5607 			if (kIOPMSleepPhase2 == sleepPhase) {
5608 				clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
5609 
5610 				if (!_standbyTimerResetSeconds ||
5611 				    (now_secs <= _standbyTimerResetSeconds)) {
5612 					// Reset standby timer adjustment
5613 					_standbyTimerResetSeconds = now_secs;
5614 					DLOG("standby delay %u, reset %u\n",
5615 					    standbyDelay, (uint32_t) _standbyTimerResetSeconds);
5616 				} else if (standbyDelay) {
5617 					// Shorten the standby delay timer
5618 					clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
5619 					if (standbyDelay > elapsed) {
5620 						standbyDelay -= elapsed;
5621 					} else {
5622 						standbyDelay = 1; // must be > 0
5623 					}
5624 					DLOG("standby delay %u, elapsed %u\n",
5625 					    standbyDelay, (uint32_t) elapsed);
5626 				}
5627 			}
5628 			params->ecWakeTimer = standbyDelay;
5629 		} else if (kIOPMSleepPhase2 == sleepPhase) {
5630 			// A sleep that does not enable the sleep timer will reset
5631 			// the standby delay adjustment.
5632 			_standbyTimerResetSeconds = 0;
5633 		}
5634 		break;
5635 	}
5636 
5637 done:
5638 	return found;
5639 }
5640 
5641 static IOPMSystemSleepParameters gEarlySystemSleepParams;
5642 
5643 void
5644 IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
5645 {
5646 	// Evaluate early (priority interest phase), before drivers sleep.
5647 
5648 	DLOG("%s\n", __FUNCTION__);
5649 	removeProperty(kIOPMSystemSleepParametersKey);
5650 
5651 	// Full wake resets the standby timer delay adjustment
5652 	if (_highestCapability & kIOPMSystemCapabilityGraphics) {
5653 		_standbyTimerResetSeconds = 0;
5654 	}
5655 
5656 	hibernateDisabled = false;
5657 	hibernateMode = 0;
5658 	getSleepOption(kIOHibernateModeKey, &hibernateMode);
5659 
5660 	// Save for late evaluation if sleep is aborted
5661 	bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
5662 
5663 	if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
5664 	    &hibernateMode)) {
5665 		if (!hibernateRetry &&
5666 		    ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
5667 		    kIOPMSleepAttributeHibernateSetup) == 0)) {
5668 			// skip hibernate setup
5669 			hibernateDisabled = true;
5670 		}
5671 	}
5672 
5673 	// Publish IOPMSystemSleepType
5674 	uint32_t sleepType = gEarlySystemSleepParams.sleepType;
5675 	if (sleepType == kIOPMSleepTypeInvalid) {
5676 		// no sleep policy
5677 		sleepType = kIOPMSleepTypeNormalSleep;
5678 		if (hibernateMode & kIOHibernateModeOn) {
5679 			sleepType = (hibernateMode & kIOHibernateModeSleep) ?
5680 			    kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
5681 		}
5682 	} else if ((sleepType == kIOPMSleepTypeStandby) &&
5683 	    (gEarlySystemSleepParams.ecPoweroffTimer)) {
5684 		// report the lowest possible sleep state
5685 		sleepType = kIOPMSleepTypePowerOff;
5686 	}
5687 
5688 	setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
5689 }
5690 
5691 void
5692 IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
5693 {
5694 	IOPMSystemSleepParameters   params;
5695 	OSSharedPtr<OSData>         paramsData;
5696 	bool                        wakeNow;
5697 	// Evaluate sleep policy after sleeping drivers but before platform sleep.
5698 
5699 	DLOG("%s\n", __FUNCTION__);
5700 
5701 	bzero(&params, sizeof(params));
5702 	wakeNow = false;
5703 	if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode)) {
5704 		if ((kIOPMSleepTypeStandby == params.sleepType)
5705 		    && gIOHibernateStandbyDisabled && gSleepPolicyVars
5706 		    && (!((kIOPMSleepFactorStandbyForced | kIOPMSleepFactorAutoPowerOffForced | kIOPMSleepFactorHibernateForced)
5707 		    & gSleepPolicyVars->sleepFactors))) {
5708 			standbyNixed = true;
5709 			wakeNow = true;
5710 		}
5711 		if (wakeNow
5712 		    || ((hibernateDisabled || hibernateAborted) &&
5713 		    (getSleepTypeAttributes(params.sleepType) &
5714 		    kIOPMSleepAttributeHibernateSetup))) {
5715 			// Final evaluation picked a state requiring hibernation,
5716 			// but hibernate isn't going to proceed. Arm a short sleep using
5717 			// the early non-hibernate sleep parameters.
5718 			bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
5719 			params.sleepType = kIOPMSleepTypeAbortedSleep;
5720 			params.ecWakeTimer = 1;
5721 			if (standbyNixed) {
5722 				resetTimers = true;
5723 			} else {
5724 				// Set hibernateRetry flag to force hibernate setup on the
5725 				// next sleep.
5726 				hibernateRetry = true;
5727 			}
5728 			DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d, standbyNixed %d\n",
5729 			    params.ecWakeTimer, hibernateDisabled, hibernateAborted, standbyNixed);
5730 		} else {
5731 			hibernateRetry = false;
5732 		}
5733 
5734 		if (kIOPMSleepTypeAbortedSleep != params.sleepType) {
5735 			resetTimers = false;
5736 		}
5737 
5738 		paramsData = OSData::withValue(params);
5739 		if (paramsData) {
5740 			setProperty(kIOPMSystemSleepParametersKey, paramsData.get());
5741 		}
5742 
5743 		if (getSleepTypeAttributes(params.sleepType) &
5744 		    kIOPMSleepAttributeHibernateSleep) {
5745 			// Disable sleep to force hibernation
5746 			gIOHibernateMode &= ~kIOHibernateModeSleep;
5747 		}
5748 	}
5749 }
5750 
5751 bool
5752 IOPMrootDomain::getHibernateSettings(
5753 	uint32_t *  hibernateModePtr,
5754 	uint32_t *  hibernateFreeRatio,
5755 	uint32_t *  hibernateFreeTime )
5756 {
5757 	// Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
5758 	// has updated the hibernateDisabled flag.
5759 
5760 	bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
5761 	getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
5762 	getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
5763 	if (hibernateDisabled) {
5764 		*hibernateModePtr = 0;
5765 	} else if (gSleepPolicyHandler) {
5766 		*hibernateModePtr = hibernateMode;
5767 	}
5768 	DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
5769 	return ok;
5770 }
5771 
5772 bool
5773 IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
5774 {
5775 	OSSharedPtr<OSObject>       optionsProp;
5776 	OSDictionary *              optionsDict;
5777 	OSSharedPtr<OSObject>       obj;
5778 	OSNumber *                  num;
5779 	bool                        ok = false;
5780 
5781 	optionsProp = copyProperty(kRootDomainSleepOptionsKey);
5782 	optionsDict = OSDynamicCast(OSDictionary, optionsProp.get());
5783 
5784 	if (optionsDict) {
5785 		obj.reset(optionsDict->getObject(key), OSRetain);
5786 	}
5787 	if (!obj) {
5788 		obj = copyProperty(key);
5789 	}
5790 	if (obj) {
5791 		if ((num = OSDynamicCast(OSNumber, obj.get()))) {
5792 			*option = num->unsigned32BitValue();
5793 			ok = true;
5794 		} else if (OSDynamicCast(OSBoolean, obj.get())) {
5795 			*option = (obj == kOSBooleanTrue) ? 1 : 0;
5796 			ok = true;
5797 		}
5798 	}
5799 
5800 	return ok;
5801 }
5802 #endif /* HIBERNATION */
5803 
5804 IOReturn
5805 IOPMrootDomain::getSystemSleepType( uint32_t * sleepType, uint32_t * standbyTimer )
5806 {
5807 #if HIBERNATION
5808 	IOPMSystemSleepParameters   params;
5809 	uint32_t                    hibMode = 0;
5810 	bool                        ok;
5811 
5812 	if (gIOPMWorkLoop->inGate() == false) {
5813 		IOReturn ret = gIOPMWorkLoop->runAction(
5814 			OSMemberFunctionCast(IOWorkLoop::Action, this,
5815 			&IOPMrootDomain::getSystemSleepType),
5816 			(OSObject *) this,
5817 			(void *) sleepType, (void *) standbyTimer);
5818 		return ret;
5819 	}
5820 
5821 	getSleepOption(kIOHibernateModeKey, &hibMode);
5822 	bzero(&params, sizeof(params));
5823 
5824 	ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
5825 	if (ok) {
5826 		*sleepType = params.sleepType;
5827 		if (!getSleepOption(kIOPMDeepSleepTimerKey, standbyTimer) &&
5828 		    !getSleepOption(kIOPMDeepSleepDelayKey, standbyTimer)) {
5829 			DLOG("Standby delay is not set\n");
5830 			*standbyTimer = 0;
5831 		}
5832 		return kIOReturnSuccess;
5833 	}
5834 #endif
5835 
5836 	return kIOReturnUnsupported;
5837 }
5838 
5839 // MARK: -
5840 // MARK: Shutdown and Restart
5841 
5842 //******************************************************************************
5843 // handlePlatformHaltRestart
5844 //
5845 //******************************************************************************
5846 
5847 // Phases while performing shutdown/restart
5848 typedef enum {
5849 	kNotifyDone                 = 0x00,
5850 	kNotifyPriorityClients      = 0x10,
5851 	kNotifyPowerPlaneDrivers    = 0x20,
5852 	kNotifyHaltRestartAction    = 0x30,
5853 	kQuiescePM                  = 0x40,
5854 } shutdownPhase_t;
5855 
5856 
5857 struct HaltRestartApplierContext {
5858 	IOPMrootDomain *    RootDomain;
5859 	unsigned long       PowerState;
5860 	IOPMPowerFlags      PowerFlags;
5861 	UInt32              MessageType;
5862 	UInt32              Counter;
5863 	const char *        LogString;
5864 	shutdownPhase_t     phase;
5865 
5866 	IOServiceInterestHandler    handler;
5867 } gHaltRestartCtx;
5868 
5869 const char *
5870 shutdownPhase2String(shutdownPhase_t phase)
5871 {
5872 	switch (phase) {
5873 	case kNotifyDone:
5874 		return "Notifications completed";
5875 	case kNotifyPriorityClients:
5876 		return "Notifying priority clients";
5877 	case kNotifyPowerPlaneDrivers:
5878 		return "Notifying power plane drivers";
5879 	case kNotifyHaltRestartAction:
5880 		return "Notifying HaltRestart action handlers";
5881 	case kQuiescePM:
5882 		return "Quiescing PM";
5883 	default:
5884 		return "Unknown";
5885 	}
5886 }
5887 
5888 static void
5889 platformHaltRestartApplier( OSObject * object, void * context )
5890 {
5891 	IOPowerStateChangeNotification  notify;
5892 	HaltRestartApplierContext *     ctx;
5893 	AbsoluteTime                    startTime, elapsedTime;
5894 	uint32_t                        deltaTime;
5895 
5896 	ctx = (HaltRestartApplierContext *) context;
5897 
5898 	_IOServiceInterestNotifier * notifier;
5899 	notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5900 	memset(&notify, 0, sizeof(notify));
5901 	notify.powerRef    = (void *)(uintptr_t)ctx->Counter;
5902 	notify.returnValue = 0;
5903 	notify.stateNumber = ctx->PowerState;
5904 	notify.stateFlags  = ctx->PowerFlags;
5905 
5906 	if (notifier) {
5907 		ctx->handler = notifier->handler;
5908 	}
5909 
5910 	clock_get_uptime(&startTime);
5911 	ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
5912 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
5913 
5914 	if ((deltaTime > kPMHaltTimeoutMS) && notifier) {
5915 		LOG("%s handler %p took %u ms\n",
5916 		    ctx->LogString, OBFUSCATE(notifier->handler), deltaTime);
5917 		halt_log_enter("PowerOff/Restart message to priority client", (const void *) notifier->handler, elapsedTime);
5918 	}
5919 
5920 	ctx->handler = NULL;
5921 	ctx->Counter++;
5922 }
5923 
5924 static void
5925 quiescePowerTreeCallback( void * target, void * param )
5926 {
5927 	IOLockLock(gPMHaltLock);
5928 	gPMQuiesced = true;
5929 	thread_wakeup(param);
5930 	IOLockUnlock(gPMHaltLock);
5931 }
5932 
5933 void
5934 IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
5935 {
5936 	AbsoluteTime                startTime, elapsedTime;
5937 	uint32_t                    deltaTime;
5938 	bool                        nvramSync = false;
5939 
5940 	memset(&gHaltRestartCtx, 0, sizeof(gHaltRestartCtx));
5941 	gHaltRestartCtx.RootDomain = this;
5942 
5943 	clock_get_uptime(&startTime);
5944 	switch (pe_type) {
5945 	case kPEHaltCPU:
5946 	case kPEUPSDelayHaltCPU:
5947 		gHaltRestartCtx.PowerState  = OFF_STATE;
5948 		gHaltRestartCtx.MessageType = kIOMessageSystemWillPowerOff;
5949 		gHaltRestartCtx.LogString   = "PowerOff";
5950 		nvramSync = true;
5951 		break;
5952 
5953 	case kPERestartCPU:
5954 		gHaltRestartCtx.PowerState  = RESTART_STATE;
5955 		gHaltRestartCtx.MessageType = kIOMessageSystemWillRestart;
5956 		gHaltRestartCtx.LogString   = "Restart";
5957 		nvramSync = true;
5958 		break;
5959 
5960 	case kPEPagingOff:
5961 		gHaltRestartCtx.PowerState  = ON_STATE;
5962 		gHaltRestartCtx.MessageType = kIOMessageSystemPagingOff;
5963 		gHaltRestartCtx.LogString   = "PagingOff";
5964 		IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
5965 #if HIBERNATION
5966 		IOHibernateSystemRestart();
5967 #endif
5968 		break;
5969 
5970 	default:
5971 		return;
5972 	}
5973 
5974 	if (nvramSync) {
5975 		PESyncNVRAM();
5976 	}
5977 
5978 	gHaltRestartCtx.phase = kNotifyPriorityClients;
5979 	// Notify legacy clients
5980 	applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &gHaltRestartCtx);
5981 
5982 	// For normal shutdown, turn off File Server Mode.
5983 	if (kPEHaltCPU == pe_type) {
5984 		OSSharedPtr<const OSSymbol> setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
5985 		OSSharedPtr<OSNumber> num = OSNumber::withNumber((unsigned long long) 0, 32);
5986 		if (setting && num) {
5987 			setPMSetting(setting.get(), num.get());
5988 		}
5989 	}
5990 
5991 	if (kPEPagingOff != pe_type) {
5992 		gHaltRestartCtx.phase = kNotifyPowerPlaneDrivers;
5993 		// Notify in power tree order
5994 		notifySystemShutdown(this, gHaltRestartCtx.MessageType);
5995 	}
5996 
5997 	gHaltRestartCtx.phase = kNotifyHaltRestartAction;
5998 #if defined(XNU_TARGET_OS_OSX)
5999 	IOCPURunPlatformHaltRestartActions(pe_type);
6000 #else /* !defined(XNU_TARGET_OS_OSX) */
6001 	if (kPEPagingOff != pe_type) {
6002 		IOCPURunPlatformHaltRestartActions(pe_type);
6003 	}
6004 #endif /* !defined(XNU_TARGET_OS_OSX) */
6005 
6006 	// Wait for PM to quiesce
6007 	if ((kPEPagingOff != pe_type) && gPMHaltLock) {
6008 		gHaltRestartCtx.phase = kQuiescePM;
6009 		AbsoluteTime quiesceTime = mach_absolute_time();
6010 
6011 		IOLockLock(gPMHaltLock);
6012 		gPMQuiesced = false;
6013 		if (quiescePowerTree(this, &quiescePowerTreeCallback, &gPMQuiesced) ==
6014 		    kIOReturnSuccess) {
6015 			while (!gPMQuiesced) {
6016 				IOLockSleep(gPMHaltLock, &gPMQuiesced, THREAD_UNINT);
6017 			}
6018 		}
6019 		IOLockUnlock(gPMHaltLock);
6020 		deltaTime = computeDeltaTimeMS(&quiesceTime, &elapsedTime);
6021 		DLOG("PM quiesce took %u ms\n", deltaTime);
6022 		halt_log_enter("Quiesce", NULL, elapsedTime);
6023 	}
6024 	gHaltRestartCtx.phase = kNotifyDone;
6025 
6026 	deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
6027 	LOG("%s all drivers took %u ms\n", gHaltRestartCtx.LogString, deltaTime);
6028 
6029 	halt_log_enter(gHaltRestartCtx.LogString, NULL, elapsedTime);
6030 
6031 	deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
6032 	LOG("%s total %u ms\n", gHaltRestartCtx.LogString, deltaTime);
6033 
6034 	if (gHaltLog && gHaltTimeMaxLog && (deltaTime >= gHaltTimeMaxLog)) {
6035 		printf("%s total %d ms:%s\n", gHaltRestartCtx.LogString, deltaTime, gHaltLog);
6036 	}
6037 
6038 	checkShutdownTimeout();
6039 }
6040 
6041 bool
6042 IOPMrootDomain::checkShutdownTimeout()
6043 {
6044 	AbsoluteTime   elapsedTime;
6045 	uint32_t deltaTime = computeDeltaTimeMS(&gHaltStartTime, &elapsedTime);
6046 
6047 	if (gHaltTimeMaxPanic && (deltaTime >= gHaltTimeMaxPanic)) {
6048 		return true;
6049 	}
6050 	return false;
6051 }
6052 
6053 void
6054 IOPMrootDomain::panicWithShutdownLog(uint32_t timeoutInMs)
6055 {
6056 	if (gHaltLog) {
6057 		if ((gHaltRestartCtx.phase == kNotifyPriorityClients) && gHaltRestartCtx.handler) {
6058 			halt_log_enter("Blocked on priority client", (void *)gHaltRestartCtx.handler, mach_absolute_time() - gHaltStartTime);
6059 		}
6060 		panic("%s timed out in phase '%s'. Total %d ms:%s",
6061 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs, gHaltLog);
6062 	} else {
6063 		panic("%s timed out in phase \'%s\'. Total %d ms",
6064 		    gHaltRestartCtx.LogString, shutdownPhase2String(gHaltRestartCtx.phase), timeoutInMs);
6065 	}
6066 }
6067 
6068 //******************************************************************************
6069 // shutdownSystem
6070 //
6071 //******************************************************************************
6072 
6073 IOReturn
6074 IOPMrootDomain::shutdownSystem( void )
6075 {
6076 	return kIOReturnUnsupported;
6077 }
6078 
6079 //******************************************************************************
6080 // restartSystem
6081 //
6082 //******************************************************************************
6083 
6084 IOReturn
6085 IOPMrootDomain::restartSystem( void )
6086 {
6087 	return kIOReturnUnsupported;
6088 }
6089 
6090 // MARK: -
6091 // MARK: System Capability
6092 
6093 //******************************************************************************
6094 // tagPowerPlaneService
6095 //
6096 // Running on PM work loop thread.
6097 //******************************************************************************
6098 
6099 void
6100 IOPMrootDomain::tagPowerPlaneService(
6101 	IOService *         service,
6102 	IOPMActions *       actions,
6103 	IOPMPowerStateIndex maxPowerState )
6104 {
6105 	uint32_t    flags = 0;
6106 
6107 	memset(actions, 0, sizeof(*actions));
6108 	actions->target = this;
6109 
6110 	if (service == this) {
6111 		actions->actionPowerChangeStart =
6112 		    OSMemberFunctionCast(
6113 			IOPMActionPowerChangeStart, this,
6114 			&IOPMrootDomain::handleOurPowerChangeStart);
6115 
6116 		actions->actionPowerChangeDone =
6117 		    OSMemberFunctionCast(
6118 			IOPMActionPowerChangeDone, this,
6119 			&IOPMrootDomain::handleOurPowerChangeDone);
6120 
6121 		actions->actionPowerChangeOverride =
6122 		    OSMemberFunctionCast(
6123 			IOPMActionPowerChangeOverride, this,
6124 			&IOPMrootDomain::overrideOurPowerChange);
6125 		return;
6126 	}
6127 
6128 #if DISPLAY_WRANGLER_PRESENT
6129 	if (NULL != service->metaCast("IODisplayWrangler")) {
6130 		// XXX should this really retain?
6131 		wrangler.reset(service, OSRetain);
6132 		wrangler->registerInterest(gIOGeneralInterest,
6133 		    &displayWranglerNotification, this, NULL);
6134 
6135 		// found the display wrangler, check for any display assertions already created
6136 		if (pmAssertions->getActivatedAssertions() & kIOPMDriverAssertionPreventDisplaySleepBit) {
6137 			DLOG("wrangler setIgnoreIdleTimer\(1) due to pre-existing assertion\n");
6138 			wrangler->setIgnoreIdleTimer( true );
6139 		}
6140 		flags |= kPMActionsFlagIsDisplayWrangler;
6141 	}
6142 #endif /* DISPLAY_WRANGLER_PRESENT */
6143 
6144 	if (service->propertyExists("IOPMStrictTreeOrder")) {
6145 		flags |= kPMActionsFlagIsGraphicsDriver;
6146 	}
6147 	if (service->propertyExists("IOPMUnattendedWakePowerState")) {
6148 		flags |= kPMActionsFlagIsAudioDriver;
6149 	}
6150 
6151 	// Find the power connection object that is a child of the PCI host
6152 	// bridge, and has a graphics/audio device attached below. Mark the
6153 	// power branch for delayed child notifications.
6154 
6155 	if (flags) {
6156 		IORegistryEntry * child  = service;
6157 		IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
6158 
6159 		while (child != this) {
6160 			if (child->propertyHasValue("IOPCITunnelled", kOSBooleanTrue)) {
6161 				// Skip delaying notifications and clamping power on external graphics and audio devices.
6162 				DLOG("Avoiding delayChildNotification on object 0x%llx. flags: 0x%x\n", service->getRegistryEntryID(), flags);
6163 				flags = 0;
6164 				break;
6165 			}
6166 			if ((parent == pciHostBridgeDriver) ||
6167 			    (parent == this)) {
6168 				if (OSDynamicCast(IOPowerConnection, child)) {
6169 					IOPowerConnection * conn = (IOPowerConnection *) child;
6170 					conn->delayChildNotification = true;
6171 					DLOG("delayChildNotification for 0x%llx\n", conn->getRegistryEntryID());
6172 				}
6173 				break;
6174 			}
6175 			child = parent;
6176 			parent = child->getParentEntry(gIOPowerPlane);
6177 		}
6178 	}
6179 
6180 	OSSharedPtr<OSObject> prop = service->copyProperty(kIOPMDarkWakeMaxPowerStateKey);
6181 	if (prop) {
6182 		OSNumber * num = OSDynamicCast(OSNumber, prop.get());
6183 		if (num) {
6184 			actions->darkWakePowerState = num->unsigned32BitValue();
6185 			if (actions->darkWakePowerState < maxPowerState) {
6186 				flags |= kPMActionsFlagHasDarkWakePowerState;
6187 			}
6188 		}
6189 	}
6190 
6191 
6192 	if (flags) {
6193 		DLOG("%s tag flags %x\n", service->getName(), flags);
6194 		actions->flags |= flags;
6195 		actions->actionPowerChangeOverride =
6196 		    OSMemberFunctionCast(
6197 			IOPMActionPowerChangeOverride, this,
6198 			&IOPMrootDomain::overridePowerChangeForService);
6199 
6200 		if (flags & kPMActionsFlagIsDisplayWrangler) {
6201 			actions->actionActivityTickle =
6202 			    OSMemberFunctionCast(
6203 				IOPMActionActivityTickle, this,
6204 				&IOPMrootDomain::handleActivityTickleForDisplayWrangler);
6205 
6206 			actions->actionUpdatePowerClient =
6207 			    OSMemberFunctionCast(
6208 				IOPMActionUpdatePowerClient, this,
6209 				&IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
6210 		}
6211 		return;
6212 	}
6213 
6214 	// Locate the first PCI host bridge for PMTrace.
6215 	if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge")) {
6216 		IOService * provider = service->getProvider();
6217 		if (OSDynamicCast(IOPlatformDevice, provider) &&
6218 		    provider->inPlane(gIODTPlane)) {
6219 			pciHostBridgeDevice.reset(provider, OSNoRetain);
6220 			pciHostBridgeDriver.reset(service, OSNoRetain);
6221 			DLOG("PMTrace found PCI host bridge %s->%s\n",
6222 			    provider->getName(), service->getName());
6223 		}
6224 	}
6225 
6226 	// Tag top-level PCI devices. The order of PMinit() call does not
6227 	// change across boots and is used as the PCI bit number.
6228 	if (pciHostBridgeDevice && service->metaCast("IOPCIDevice")) {
6229 		// Would prefer to check built-in property, but tagPowerPlaneService()
6230 		// is called before pciDevice->registerService().
6231 		IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
6232 		if ((parent == pciHostBridgeDevice) && service->propertyExists("acpi-device")) {
6233 			int bit = pmTracer->recordTopLevelPCIDevice( service );
6234 			if (bit >= 0) {
6235 				// Save the assigned bit for fast lookup.
6236 				actions->flags |= (bit & kPMActionsPCIBitNumberMask);
6237 
6238 				actions->actionPowerChangeStart =
6239 				    OSMemberFunctionCast(
6240 					IOPMActionPowerChangeStart, this,
6241 					&IOPMrootDomain::handlePowerChangeStartForPCIDevice);
6242 
6243 				actions->actionPowerChangeDone =
6244 				    OSMemberFunctionCast(
6245 					IOPMActionPowerChangeDone, this,
6246 					&IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
6247 			}
6248 		}
6249 	}
6250 }
6251 
6252 //******************************************************************************
6253 // PM actions for root domain
6254 //******************************************************************************
6255 
6256 void
6257 IOPMrootDomain::overrideOurPowerChange(
6258 	IOService *             service,
6259 	IOPMActions *           actions,
6260 	const IOPMRequest *     request,
6261 	IOPMPowerStateIndex *   inOutPowerState,
6262 	IOPMPowerChangeFlags *  inOutChangeFlags )
6263 {
6264 	uint32_t changeFlags = *inOutChangeFlags;
6265 	uint32_t desiredPowerState = (uint32_t) *inOutPowerState;
6266 	uint32_t currentPowerState = (uint32_t) getPowerState();
6267 
6268 	if (request->getTag() == 0) {
6269 		// Set a tag for any request that originates from IOServicePM
6270 		(const_cast<IOPMRequest *>(request))->fTag = nextRequestTag(kCPSReasonPMInternals);
6271 	}
6272 
6273 	DLOG("PowerChangeOverride (%s->%s, %x, 0x%x) tag 0x%x\n",
6274 	    getPowerStateString(currentPowerState),
6275 	    getPowerStateString(desiredPowerState),
6276 	    _currentCapability, changeFlags,
6277 	    request->getTag());
6278 
6279 
6280 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6281 	/*
6282 	 * ASBM send lowBattery notifications every 1 second until the device
6283 	 * enters hibernation. This queues up multiple sleep requests.
6284 	 * After the device wakes from hibernation, none of these previously
6285 	 * queued sleep requests are valid.
6286 	 * lowBattteryCondition variable is set when ASBM notifies rootDomain
6287 	 * and is cleared at the very last point in sleep.
6288 	 * Any attempt to sleep with reason kIOPMSleepReasonLowPower without
6289 	 * lowBatteryCondition is invalid
6290 	 */
6291 	if (REQUEST_TAG_TO_REASON(request->getTag()) == kIOPMSleepReasonLowPower) {
6292 		if (!lowBatteryCondition) {
6293 			DLOG("Duplicate lowBattery sleep");
6294 			*inOutChangeFlags |= kIOPMNotDone;
6295 			return;
6296 		}
6297 	}
6298 #endif
6299 
6300 	if ((AOT_STATE == desiredPowerState) && (ON_STATE == currentPowerState)) {
6301 		// Assertion may have been taken in AOT leading to changePowerStateTo(AOT)
6302 		*inOutChangeFlags |= kIOPMNotDone;
6303 		return;
6304 	}
6305 
6306 	if (changeFlags & kIOPMParentInitiated) {
6307 		// Root parent is permanently pegged at max power,
6308 		// a parent initiated power change is unexpected.
6309 		*inOutChangeFlags |= kIOPMNotDone;
6310 		return;
6311 	}
6312 
6313 #if HIBERNATION && defined(__arm64__)
6314 	if (lowBatteryCondition && (desiredPowerState < currentPowerState)) {
6315 		if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
6316 			// If hibernation is unsupported, reject sleep requests to avoid
6317 			// racing with system shutdown.
6318 			*inOutChangeFlags |= kIOPMNotDone;
6319 			return;
6320 		}
6321 	}
6322 #endif /* HIBERNATION && defined(__arm64__) */
6323 
6324 	if (desiredPowerState < currentPowerState) {
6325 		if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
6326 			// Root domain is dropping power state from ON->SLEEP.
6327 			// If system is in full wake, first enter dark wake by
6328 			// converting the power drop to a capability change.
6329 			// Once in dark wake, transition to sleep state ASAP.
6330 
6331 			darkWakeToSleepASAP = true;
6332 
6333 			// Drop graphics and audio capability
6334 			_desiredCapability &= ~(
6335 				kIOPMSystemCapabilityGraphics |
6336 				kIOPMSystemCapabilityAudio);
6337 
6338 			// Convert to capability change (ON->ON)
6339 			*inOutPowerState = getRUN_STATE();
6340 			*inOutChangeFlags |= kIOPMSynchronize;
6341 
6342 			// Revert device desire from SLEEP to ON
6343 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerOverride);
6344 		} else {
6345 			// System is already in dark wake, ok to drop power state.
6346 			// Broadcast root power down to entire tree.
6347 			*inOutChangeFlags |= kIOPMRootChangeDown;
6348 		}
6349 	} else if (desiredPowerState > currentPowerState) {
6350 		if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0) {
6351 			// Broadcast power up when waking from sleep, but not for the
6352 			// initial power change at boot by checking for cpu capability.
6353 			*inOutChangeFlags |= kIOPMRootChangeUp;
6354 		}
6355 	}
6356 }
6357 
6358 void
6359 IOPMrootDomain::handleOurPowerChangeStart(
6360 	IOService *             service,
6361 	IOPMActions *           actions,
6362 	const IOPMRequest *     request,
6363 	IOPMPowerStateIndex     newPowerState,
6364 	IOPMPowerChangeFlags *  inOutChangeFlags )
6365 {
6366 	IOPMRequestTag requestTag = request->getTag();
6367 	IOPMRequestTag sleepReason;
6368 
6369 	uint32_t changeFlags        = *inOutChangeFlags;
6370 	uint32_t currentPowerState  = (uint32_t) getPowerState();
6371 	bool     publishSleepReason = false;
6372 
6373 	// Check if request has a valid sleep reason
6374 	sleepReason = REQUEST_TAG_TO_REASON(requestTag);
6375 	if (sleepReason < kIOPMSleepReasonClamshell) {
6376 		sleepReason = kIOPMSleepReasonIdle;
6377 	}
6378 
6379 	_systemTransitionType    = kSystemTransitionNone;
6380 	_systemMessageClientMask = 0;
6381 	capabilityLoss           = false;
6382 	toldPowerdCapWillChange  = false;
6383 
6384 	// Emergency notifications may arrive after the initial sleep request
6385 	// has been queued. Override the sleep reason so powerd and others can
6386 	// treat this as an emergency sleep.
6387 	if (lowBatteryCondition) {
6388 		sleepReason = kIOPMSleepReasonLowPower;
6389 	} else if (thermalEmergencyState) {
6390 		sleepReason = kIOPMSleepReasonThermalEmergency;
6391 	}
6392 
6393 	// 1. Explicit capability change.
6394 	if (changeFlags & kIOPMSynchronize) {
6395 		if (newPowerState == ON_STATE) {
6396 			if (changeFlags & kIOPMSyncNoChildNotify) {
6397 				setSystemTransitionTypeGated(kSystemTransitionNewCapClient);
6398 			} else {
6399 				setSystemTransitionTypeGated(kSystemTransitionCapability);
6400 			}
6401 		}
6402 	}
6403 	// 2. Going to sleep (cancellation still possible).
6404 	else if (newPowerState < currentPowerState) {
6405 		setSystemTransitionTypeGated(kSystemTransitionSleep);
6406 	}
6407 	// 3. Woke from (idle or demand) sleep.
6408 	else if (!systemBooting &&
6409 	    (changeFlags & kIOPMSelfInitiated) &&
6410 	    (newPowerState > currentPowerState)) {
6411 		setSystemTransitionTypeGated(kSystemTransitionWake);
6412 
6413 		_desiredCapability = kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityNetwork;
6414 
6415 		// Early exit from dark wake to full (e.g. LID open)
6416 		if (kFullWakeReasonNone != fullWakeReason) {
6417 			_desiredCapability |= (
6418 				kIOPMSystemCapabilityGraphics |
6419 				kIOPMSystemCapabilityAudio);
6420 
6421 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
6422 			if (fullWakeReason == kFullWakeReasonLocalUser) {
6423 				darkWakeExit = true;
6424 				darkWakeToSleepASAP = false;
6425 				setProperty(kIOPMRootDomainWakeTypeKey, isRTCAlarmWake ?
6426 				    kIOPMRootDomainWakeTypeAlarm : kIOPMRootDomainWakeTypeUser);
6427 			}
6428 #endif
6429 		}
6430 #if HIBERNATION
6431 		IOHibernateSetWakeCapabilities(_desiredCapability);
6432 #endif
6433 	}
6434 
6435 	// Update pending wake capability at the beginning of every
6436 	// state transition (including synchronize). This will become
6437 	// the current capability at the end of the transition.
6438 
6439 	if (kSystemTransitionSleep == _systemTransitionType) {
6440 		_pendingCapability = 0;
6441 		capabilityLoss = true;
6442 	} else if (kSystemTransitionNewCapClient != _systemTransitionType) {
6443 		_pendingCapability = _desiredCapability |
6444 		    kIOPMSystemCapabilityCPU |
6445 		    kIOPMSystemCapabilityNetwork;
6446 
6447 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6448 			_pendingCapability |= kIOPMSystemCapabilityAudio;
6449 		}
6450 
6451 		if ((kSystemTransitionCapability == _systemTransitionType) &&
6452 		    (_pendingCapability == _currentCapability)) {
6453 			// Cancel the PM state change.
6454 			setSystemTransitionTypeGated(kSystemTransitionNone);
6455 			*inOutChangeFlags |= kIOPMNotDone;
6456 		}
6457 		if (__builtin_popcount(_pendingCapability) <
6458 		    __builtin_popcount(_currentCapability)) {
6459 			capabilityLoss = true;
6460 		}
6461 	}
6462 
6463 	// 1. Capability change.
6464 	if (kSystemTransitionCapability == _systemTransitionType) {
6465 		// Dark to Full transition.
6466 		if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6467 			tracePoint( kIOPMTracePointDarkWakeExit );
6468 
6469 #if defined(XNU_TARGET_OS_OSX)
6470 			// rdar://problem/65627936
6471 			// When a dark->full wake promotion is scheduled before an ON->SLEEP
6472 			// power state drop, invalidate any request to drop power state already
6473 			// in the queue, including the override variant, unless full wake cannot
6474 			// be sustained. Any power state drop queued after this SustainFullWake
6475 			// request will not be affected.
6476 			if (checkSystemCanSustainFullWake()) {
6477 				changePowerStateWithOverrideTo(getRUN_STATE(), kCPSReasonSustainFullWake);
6478 			}
6479 #endif
6480 
6481 			willEnterFullWake();
6482 		}
6483 
6484 		// Full to Dark transition.
6485 		if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6486 			// Clear previous stats
6487 			IOLockLock(pmStatsLock);
6488 			if (pmStatsAppResponses) {
6489 				pmStatsAppResponses = OSArray::withCapacity(5);
6490 			}
6491 			IOLockUnlock(pmStatsLock);
6492 
6493 			tracePoint( kIOPMTracePointDarkWakeEntry );
6494 			*inOutChangeFlags |= kIOPMSyncTellPowerDown;
6495 			_systemMessageClientMask = kSystemMessageClientPowerd |
6496 			    kSystemMessageClientLegacyApp;
6497 
6498 			// rdar://15971327
6499 			// Prevent user active transitions before notifying clients
6500 			// that system will sleep.
6501 			preventTransitionToUserActive(true);
6502 
6503 			IOService::setAdvisoryTickleEnable( false );
6504 
6505 			// Publish the sleep reason for full to dark wake
6506 			publishSleepReason = true;
6507 			lastSleepReason = fullToDarkReason = sleepReason;
6508 
6509 			// Publish a UUID for the Sleep --> Wake cycle
6510 			handlePublishSleepWakeUUID(true);
6511 			if (sleepDelaysReport) {
6512 				clock_get_uptime(&ts_sleepStart);
6513 				DLOG("sleepDelaysReport f->9 start at 0x%llx\n", ts_sleepStart);
6514 			}
6515 
6516 			darkWakeExit = false;
6517 		}
6518 	}
6519 	// 2. System sleep.
6520 	else if (kSystemTransitionSleep == _systemTransitionType) {
6521 		// Beginning of a system sleep transition.
6522 		// Cancellation is still possible.
6523 		tracePoint( kIOPMTracePointSleepStarted );
6524 
6525 		_systemMessageClientMask = kSystemMessageClientAll;
6526 		if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0) {
6527 			_systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
6528 		}
6529 		if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
6530 			// Kernel priority clients are only notified on the initial
6531 			// transition to full wake, so don't notify them unless system
6532 			// has gained graphics capability since the last system wake.
6533 			_systemMessageClientMask &= ~kSystemMessageClientKernel;
6534 		} else {
6535 			// System was in full wake, but the downwards power transition is driven
6536 			// by a request that originates from IOServicePM, so it isn't tagged with
6537 			// a valid system sleep reason.
6538 			if (REQUEST_TAG_TO_REASON(requestTag) == kCPSReasonPMInternals) {
6539 				// Publish the same reason for full to dark
6540 				sleepReason = fullToDarkReason;
6541 			}
6542 		}
6543 #if HIBERNATION
6544 		gIOHibernateState = 0;
6545 #endif
6546 
6547 		// Record the reason for dark wake back to sleep
6548 		// System may not have ever achieved full wake
6549 
6550 		publishSleepReason = true;
6551 		lastSleepReason = sleepReason;
6552 		if (sleepDelaysReport) {
6553 			clock_get_uptime(&ts_sleepStart);
6554 			DLOG("sleepDelaysReport 9->0 start at 0x%llx\n", ts_sleepStart);
6555 		}
6556 	}
6557 	// 3. System wake.
6558 	else if (kSystemTransitionWake == _systemTransitionType) {
6559 		tracePoint( kIOPMTracePointWakeWillPowerOnClients );
6560 		// Clear stats about sleep
6561 
6562 		if (AOT_STATE == newPowerState) {
6563 			_pendingCapability = kIOPMSystemCapabilityAOT;
6564 		}
6565 
6566 		if (AOT_STATE == currentPowerState) {
6567 			// Wake events are no longer accepted after waking to AOT_STATE.
6568 			// Re-enable wake event acceptance to append wake events claimed
6569 			// during the AOT to ON_STATE transition.
6570 			acceptSystemWakeEvents(kAcceptSystemWakeEvents_Reenable);
6571 		}
6572 
6573 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6574 			willEnterFullWake();
6575 		}
6576 	}
6577 
6578 	// The only location where the sleep reason is published. At this point
6579 	// sleep can still be cancelled, but sleep reason should be published
6580 	// early for logging purposes.
6581 
6582 	if (publishSleepReason) {
6583 		static const char * IOPMSleepReasons[] =
6584 		{
6585 			kIOPMClamshellSleepKey,
6586 			kIOPMPowerButtonSleepKey,
6587 			kIOPMSoftwareSleepKey,
6588 			kIOPMOSSwitchHibernationKey,
6589 			kIOPMIdleSleepKey,
6590 			kIOPMLowPowerSleepKey,
6591 			kIOPMThermalEmergencySleepKey,
6592 			kIOPMMaintenanceSleepKey,
6593 			kIOPMSleepServiceExitKey,
6594 			kIOPMDarkWakeThermalEmergencyKey,
6595 			kIOPMNotificationWakeExitKey
6596 		};
6597 
6598 		// Record sleep cause in IORegistry
6599 		uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
6600 		if (reasonIndex < sizeof(IOPMSleepReasons) / sizeof(IOPMSleepReasons[0])) {
6601 			DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
6602 #if DEVELOPMENT || DEBUG
6603 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6604 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6605 			    "Sleep Reason", "%s\n", IOPMSleepReasons[reasonIndex]
6606 			    );
6607 #endif /* DEVELOPMENT || DEBUG */
6608 			setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
6609 		}
6610 	}
6611 
6612 	if ((kSystemTransitionNone != _systemTransitionType) &&
6613 	    (kSystemTransitionNewCapClient != _systemTransitionType)) {
6614 		_systemStateGeneration++;
6615 		systemDarkWake = false;
6616 
6617 		DLOG("=== START (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6618 		    getPowerStateString(currentPowerState),
6619 		    getPowerStateString((uint32_t) newPowerState),
6620 		    _currentCapability, _pendingCapability,
6621 		    *inOutChangeFlags, _systemStateGeneration, _systemMessageClientMask,
6622 		    requestTag);
6623 #if DEVELOPMENT || DEBUG
6624 		if (currentPowerState != (uint32_t) newPowerState) {
6625 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6626 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6627 			    "Start Power State Trans.",
6628 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6629 			    getPowerStateString(currentPowerState),
6630 			    getPowerStateString((uint32_t) newPowerState),
6631 			    _currentCapability,
6632 			    _pendingCapability,
6633 			    *inOutChangeFlags,
6634 			    _systemStateGeneration,
6635 			    _systemMessageClientMask,
6636 			    requestTag
6637 			    );
6638 		}
6639 #endif /* DEVELOPMENT || DEBUG */
6640 	}
6641 
6642 	if ((AOT_STATE == newPowerState) && (SLEEP_STATE != currentPowerState)) {
6643 		panic("illegal AOT entry from %s", getPowerStateString(currentPowerState));
6644 	}
6645 	if (_aotNow && (ON_STATE == newPowerState)) {
6646 		WAKEEVENT_LOCK();
6647 		aotShouldExit(true);
6648 		WAKEEVENT_UNLOCK();
6649 		aotExit(false);
6650 	}
6651 }
6652 
6653 void
6654 IOPMrootDomain::setSystemTransitionTypeGated(SystemTransitionType type)
6655 {
6656 	assert(gIOPMWorkLoop->inGate());
6657 	_systemTransitionType = type;
6658 	commandGate->commandWakeup(&_systemTransitionType);
6659 }
6660 
6661 void
6662 IOPMrootDomain::waitForSystemTransitionToMinPowerState(IOPMRootDomainPowerState state)
6663 {
6664 	while (true) {
6665 		IOReturn ret = gIOPMWorkLoop->runActionBlock(^{
6666 			// Block until all in progress transitions have completed.
6667 			while (_systemTransitionType != kSystemTransitionNone) {
6668 			        commandGate->commandSleep(&_systemTransitionType);
6669 			}
6670 
6671 			// Check the current power state.
6672 			if (getPowerState() >= state) {
6673 			        return kIOReturnSuccess;
6674 			}
6675 
6676 			return kIOReturnError;
6677 		});
6678 
6679 		if (ret == kIOReturnSuccess) {
6680 			break;
6681 		}
6682 	}
6683 }
6684 
6685 void
6686 IOPMrootDomain::handleOurPowerChangeDone(
6687 	IOService *             service,
6688 	IOPMActions *           actions,
6689 	const IOPMRequest *     request,
6690 	IOPMPowerStateIndex     oldPowerState,
6691 	IOPMPowerChangeFlags    changeFlags )
6692 {
6693 	if (kSystemTransitionNewCapClient == _systemTransitionType) {
6694 		setSystemTransitionTypeGated(kSystemTransitionNone);
6695 		return;
6696 	}
6697 
6698 	if (_systemTransitionType != kSystemTransitionNone) {
6699 		uint32_t currentPowerState = (uint32_t) getPowerState();
6700 
6701 		if (changeFlags & kIOPMNotDone) {
6702 			// Power down was cancelled or vetoed.
6703 			_pendingCapability = _currentCapability;
6704 			lastSleepReason = 0;
6705 
6706 			// When sleep is cancelled or reverted, don't report
6707 			// the target (lower) power state as the previous state.
6708 			oldPowerState = currentPowerState;
6709 
6710 			if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
6711 			    CAP_CURRENT(kIOPMSystemCapabilityCPU)) {
6712 #if defined(XNU_TARGET_OS_OSX)
6713 				pmPowerStateQueue->submitPowerEvent(
6714 					kPowerEventPolicyStimulus,
6715 					(void *) kStimulusDarkWakeReentry,
6716 					_systemStateGeneration );
6717 #else /* !defined(XNU_TARGET_OS_OSX) */
6718 				// On embedded, there are no factors that can prolong a
6719 				// "darkWake" when a power down is vetoed. We need to
6720 				// promote to "fullWake" at least once so that factors
6721 				// that prevent idle sleep can assert themselves if required
6722 				pmPowerStateQueue->submitPowerEvent(
6723 					kPowerEventPolicyStimulus,
6724 					(void *) kStimulusDarkWakeActivityTickle);
6725 #endif /* !defined(XNU_TARGET_OS_OSX) */
6726 			}
6727 
6728 			// Revert device desire to max.
6729 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonPowerDownCancel);
6730 		} else {
6731 			// Send message on dark wake to full wake promotion.
6732 			// tellChangeUp() handles the normal SLEEP->ON case.
6733 
6734 			if (kSystemTransitionCapability == _systemTransitionType) {
6735 				if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
6736 					lastSleepReason = 0; // stop logging wrangler tickles
6737 					tellClients(kIOMessageSystemHasPoweredOn);
6738 				}
6739 				if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
6740 					// Going dark, reset full wake state
6741 					// userIsActive will be cleared by wrangler powering down
6742 					fullWakeReason = kFullWakeReasonNone;
6743 
6744 					if (ts_sleepStart) {
6745 						clock_get_uptime(&wake2DarkwakeDelay);
6746 						SUB_ABSOLUTETIME(&wake2DarkwakeDelay, &ts_sleepStart);
6747 						DLOG("sleepDelaysReport f->9 end 0x%llx\n", wake2DarkwakeDelay);
6748 						ts_sleepStart = 0;
6749 					}
6750 				}
6751 			}
6752 
6753 			// Reset state after exiting from dark wake.
6754 
6755 			if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
6756 			    CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6757 				darkWakeMaintenance = false;
6758 				darkWakeToSleepASAP = false;
6759 				pciCantSleepValid   = false;
6760 				darkWakeSleepService = false;
6761 
6762 				if (CAP_LOSS(kIOPMSystemCapabilityCPU)) {
6763 					// Remove the influence of display power assertion
6764 					// before next system wake.
6765 					if (wrangler) {
6766 						wrangler->changePowerStateForRootDomain(
6767 							kWranglerPowerStateMin );
6768 					}
6769 					removeProperty(gIOPMUserTriggeredFullWakeKey.get());
6770 				}
6771 			}
6772 
6773 			// Entered dark mode.
6774 
6775 			if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6776 			    (_pendingCapability & kIOPMSystemCapabilityCPU)) {
6777 				// Queue an evaluation of whether to remain in dark wake,
6778 				// and for how long. This serves the purpose of draining
6779 				// any assertions from the queue.
6780 
6781 				pmPowerStateQueue->submitPowerEvent(
6782 					kPowerEventPolicyStimulus,
6783 					(void *) kStimulusDarkWakeEntry,
6784 					_systemStateGeneration );
6785 			}
6786 		}
6787 
6788 #if DEVELOPMENT || DEBUG
6789 		if (currentPowerState != (uint32_t) oldPowerState) {
6790 			record_system_event(SYSTEM_EVENT_TYPE_INFO,
6791 			    SYSTEM_EVENT_SUBSYSTEM_PMRD,
6792 			    "Finish Power State Trans.",
6793 			    "(%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6794 			    getPowerStateString((uint32_t)oldPowerState),
6795 			    getPowerStateString(currentPowerState),
6796 			    _currentCapability,
6797 			    _pendingCapability,
6798 			    changeFlags,
6799 			    _systemStateGeneration,
6800 			    _systemMessageClientMask,
6801 			    request->getTag()
6802 			    );
6803 		}
6804 #endif /* DEVELOPMENT || DEBUG */
6805 
6806 		DLOG("=== FINISH (%s->%s, %x->%x, 0x%x) gen %u, msg %x, tag %x\n",
6807 		    getPowerStateString((uint32_t) oldPowerState), getPowerStateString(currentPowerState),
6808 		    _currentCapability, _pendingCapability,
6809 		    changeFlags, _systemStateGeneration, _systemMessageClientMask,
6810 		    request->getTag());
6811 
6812 		if ((currentPowerState == ON_STATE) && pmAssertions) {
6813 			pmAssertions->reportCPUBitAccounting();
6814 		}
6815 
6816 		if (_pendingCapability & kIOPMSystemCapabilityGraphics) {
6817 			displayWakeCnt++;
6818 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
6819 			if (clamshellExists && fullWakeThreadCall) {
6820 				AbsoluteTime deadline;
6821 				clock_interval_to_deadline(DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY, kSecondScale, &deadline);
6822 				thread_call_enter_delayed(fullWakeThreadCall, deadline);
6823 			}
6824 #endif
6825 		} else if (CAP_GAIN(kIOPMSystemCapabilityCPU)) {
6826 			darkWakeCnt++;
6827 		}
6828 
6829 		// Update current system capability.
6830 		if (_currentCapability != _pendingCapability) {
6831 			_currentCapability = _pendingCapability;
6832 		}
6833 
6834 		// Update highest system capability.
6835 
6836 		_highestCapability |= _currentCapability;
6837 
6838 		if (darkWakePostTickle &&
6839 		    (kSystemTransitionWake == _systemTransitionType) &&
6840 		    (gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6841 		    kDarkWakeFlagPromotionLate) {
6842 			darkWakePostTickle = false;
6843 			reportUserInput();
6844 		} else if (darkWakeExit) {
6845 			requestFullWake( kFullWakeReasonLocalUser );
6846 		}
6847 
6848 		// Reset tracepoint at completion of capability change,
6849 		// completion of wake transition, and aborted sleep transition.
6850 
6851 		if ((_systemTransitionType == kSystemTransitionCapability) ||
6852 		    (_systemTransitionType == kSystemTransitionWake) ||
6853 		    ((_systemTransitionType == kSystemTransitionSleep) &&
6854 		    (changeFlags & kIOPMNotDone))) {
6855 			setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
6856 			tracePoint( kIOPMTracePointSystemUp );
6857 		}
6858 
6859 		setSystemTransitionTypeGated(kSystemTransitionNone);
6860 
6861 		_systemMessageClientMask = 0;
6862 		toldPowerdCapWillChange  = false;
6863 
6864 		darkWakeLogClamp = false;
6865 
6866 		if (lowBatteryCondition) {
6867 			privateSleepSystem(kIOPMSleepReasonLowPower);
6868 		} else if (thermalEmergencyState) {
6869 			privateSleepSystem(kIOPMSleepReasonThermalEmergency);
6870 		} else if ((fullWakeReason == kFullWakeReasonDisplayOn) && !displayPowerOnRequested) {
6871 			// Request for full wake is removed while system is waking up to full wake
6872 			DLOG("DisplayOn fullwake request is removed\n");
6873 			handleSetDisplayPowerOn(false);
6874 		}
6875 
6876 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
6877 			pmPowerStateQueue->submitPowerEvent(
6878 				kPowerEventReceivedPowerNotification, (void *)(uintptr_t) kLocalEvalClamshellCommand );
6879 		}
6880 	}
6881 }
6882 
6883 //******************************************************************************
6884 // PM actions for graphics and audio.
6885 //******************************************************************************
6886 
6887 void
6888 IOPMrootDomain::overridePowerChangeForService(
6889 	IOService *             service,
6890 	IOPMActions *           actions,
6891 	const IOPMRequest *     request,
6892 	IOPMPowerStateIndex *   inOutPowerState,
6893 	IOPMPowerChangeFlags *  inOutChangeFlags )
6894 {
6895 	uint32_t powerState  = (uint32_t) *inOutPowerState;
6896 	uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
6897 	const uint32_t actionFlags = actions->flags;
6898 
6899 	if (kSystemTransitionNone == _systemTransitionType) {
6900 		// Not in midst of a system transition.
6901 		// Do not set kPMActionsStatePowerClamped.
6902 	} else if ((actions->state & kPMActionsStatePowerClamped) == 0) {
6903 		bool enableClamp = false;
6904 
6905 		// For most drivers, enable the clamp during ON->Dark transition
6906 		// which has the kIOPMSynchronize flag set in changeFlags.
6907 		if ((actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6908 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6909 		    (changeFlags & kIOPMSynchronize)) {
6910 			enableClamp = true;
6911 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6912 		    ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
6913 		    ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
6914 		    (changeFlags & kIOPMSynchronize)) {
6915 			enableClamp = true;
6916 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6917 		    ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
6918 		    (changeFlags & kIOPMSynchronize)) {
6919 			enableClamp = true;
6920 		} else if ((actionFlags & kPMActionsFlagIsGraphicsDriver) &&
6921 		    (_systemTransitionType == kSystemTransitionSleep)) {
6922 			// For graphics drivers, clamp power when entering
6923 			// system sleep. Not when dropping to dark wake.
6924 			enableClamp = true;
6925 		}
6926 
6927 		if (enableClamp) {
6928 			actions->state |= kPMActionsStatePowerClamped;
6929 			DLOG("power clamp enabled %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6930 			    service->getName(), service->getRegistryEntryID(),
6931 			    _pendingCapability, powerState, changeFlags);
6932 		}
6933 	} else if ((actions->state & kPMActionsStatePowerClamped) != 0) {
6934 		bool disableClamp = false;
6935 
6936 		if ((actionFlags & (
6937 			    kPMActionsFlagIsDisplayWrangler |
6938 			    kPMActionsFlagIsGraphicsDriver)) &&
6939 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6940 			disableClamp = true;
6941 		} else if ((actionFlags & kPMActionsFlagIsAudioDriver) &&
6942 		    (_pendingCapability & kIOPMSystemCapabilityAudio)) {
6943 			disableClamp = true;
6944 		} else if ((actionFlags & kPMActionsFlagHasDarkWakePowerState) &&
6945 		    (_pendingCapability & kIOPMSystemCapabilityGraphics)) {
6946 			disableClamp = true;
6947 		}
6948 
6949 		if (disableClamp) {
6950 			actions->state &= ~kPMActionsStatePowerClamped;
6951 			DLOG("power clamp removed %s %qx, pendingCap 0x%x, ps %d, cflags 0x%x\n",
6952 			    service->getName(), service->getRegistryEntryID(),
6953 			    _pendingCapability, powerState, changeFlags);
6954 		}
6955 	}
6956 
6957 	if (actions->state & kPMActionsStatePowerClamped) {
6958 		uint32_t maxPowerState = 0;
6959 
6960 		// Determine the max power state allowed when clamp is enabled
6961 		if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange)) {
6962 			// Parent intiated power state changes
6963 			if ((service->getPowerState() > maxPowerState) &&
6964 			    (actionFlags & kPMActionsFlagIsDisplayWrangler)) {
6965 				maxPowerState++;
6966 
6967 				// Remove lingering effects of any tickle before entering
6968 				// dark wake. It will take a new tickle to return to full
6969 				// wake, so the existing tickle state is useless.
6970 
6971 				if (changeFlags & kIOPMDomainDidChange) {
6972 					*inOutChangeFlags |= kIOPMExpireIdleTimer;
6973 				}
6974 			} else if (actionFlags & kPMActionsFlagIsGraphicsDriver) {
6975 				maxPowerState++;
6976 			} else if (actionFlags & kPMActionsFlagHasDarkWakePowerState) {
6977 				maxPowerState = actions->darkWakePowerState;
6978 			}
6979 		} else {
6980 			// Deny all self-initiated changes when power is limited.
6981 			// Wrangler tickle should never defeat the limiter.
6982 			maxPowerState = service->getPowerState();
6983 		}
6984 
6985 		if (powerState > maxPowerState) {
6986 			DLOG("power clamped %s %qx, ps %u->%u, cflags 0x%x)\n",
6987 			    service->getName(), service->getRegistryEntryID(),
6988 			    powerState, maxPowerState, changeFlags);
6989 			*inOutPowerState = maxPowerState;
6990 
6991 			if (darkWakePostTickle &&
6992 			    (actionFlags & kPMActionsFlagIsDisplayWrangler) &&
6993 			    (changeFlags & kIOPMDomainWillChange) &&
6994 			    ((gDarkWakeFlags & kDarkWakeFlagPromotionMask) ==
6995 			    kDarkWakeFlagPromotionEarly)) {
6996 				darkWakePostTickle = false;
6997 				reportUserInput();
6998 			}
6999 		}
7000 
7001 		if (!darkWakePowerClamped && (changeFlags & kIOPMDomainDidChange)) {
7002 			if (darkWakeLogClamp) {
7003 				AbsoluteTime    now;
7004 				uint64_t        nsec;
7005 
7006 				clock_get_uptime(&now);
7007 				SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
7008 				absolutetime_to_nanoseconds(now, &nsec);
7009 				DLOG("dark wake power clamped after %u ms\n",
7010 				    ((int)((nsec) / NSEC_PER_MSEC)));
7011 			}
7012 			darkWakePowerClamped = true;
7013 		}
7014 	}
7015 }
7016 
7017 void
7018 IOPMrootDomain::handleActivityTickleForDisplayWrangler(
7019 	IOService *     service,
7020 	IOPMActions *   actions )
7021 {
7022 #if DISPLAY_WRANGLER_PRESENT
7023 	// Warning: Not running in PM work loop context - don't modify state !!!
7024 	// Trap tickle directed to IODisplayWrangler while running with graphics
7025 	// capability suppressed.
7026 
7027 	assert(service == wrangler);
7028 
7029 	clock_get_uptime(&userActivityTime);
7030 	bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
7031 	    || (lastSleepReason == kIOPMSleepReasonMaintenance)
7032 	    || (lastSleepReason == kIOPMSleepReasonSoftware));
7033 	if (aborting) {
7034 		userActivityCount++;
7035 		DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
7036 		    userActivityCount, lastSleepReason);
7037 	}
7038 
7039 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7040 		DLOG("display wrangler tickled\n");
7041 		if (kIOLogPMRootDomain & gIOKitDebug) {
7042 			OSReportWithBacktrace("Dark wake display tickle");
7043 		}
7044 		if (pmPowerStateQueue) {
7045 			pmPowerStateQueue->submitPowerEvent(
7046 				kPowerEventPolicyStimulus,
7047 				(void *) kStimulusDarkWakeActivityTickle,
7048 				true /* set wake type */ );
7049 		}
7050 	}
7051 #endif /* DISPLAY_WRANGLER_PRESENT */
7052 }
7053 
7054 void
7055 IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
7056 	IOService *             service,
7057 	IOPMActions *           actions,
7058 	const OSSymbol *        powerClient,
7059 	IOPMPowerStateIndex     oldPowerState,
7060 	IOPMPowerStateIndex     newPowerState )
7061 {
7062 #if DISPLAY_WRANGLER_PRESENT
7063 	assert(service == wrangler);
7064 
7065 	// This function implements half of the user active detection
7066 	// by monitoring changes to the display wrangler's device desire.
7067 	//
7068 	// User becomes active when either:
7069 	// 1. Wrangler's DeviceDesire increases to max, but wrangler is already
7070 	//    in max power state. This desire change in absence of a power state
7071 	//    change is detected within. This handles the case when user becomes
7072 	//    active while the display is already lit by setDisplayPowerOn().
7073 	//
7074 	// 2. Power state change to max, and DeviceDesire is also at max.
7075 	//    Handled by displayWranglerNotification().
7076 	//
7077 	// User becomes inactive when DeviceDesire drops to sleep state or below.
7078 
7079 	DLOG("wrangler %s (ps %u, %u->%u)\n",
7080 	    powerClient->getCStringNoCopy(),
7081 	    (uint32_t) service->getPowerState(),
7082 	    (uint32_t) oldPowerState, (uint32_t) newPowerState);
7083 
7084 	if (powerClient == gIOPMPowerClientDevice) {
7085 		if ((newPowerState > oldPowerState) &&
7086 		    (newPowerState == kWranglerPowerStateMax) &&
7087 		    (service->getPowerState() == kWranglerPowerStateMax)) {
7088 			evaluatePolicy( kStimulusEnterUserActiveState );
7089 		} else if ((newPowerState < oldPowerState) &&
7090 		    (newPowerState <= kWranglerPowerStateSleep)) {
7091 			evaluatePolicy( kStimulusLeaveUserActiveState );
7092 		}
7093 	}
7094 
7095 	if (newPowerState <= kWranglerPowerStateSleep) {
7096 		evaluatePolicy( kStimulusDisplayWranglerSleep );
7097 	} else if (newPowerState == kWranglerPowerStateMax) {
7098 		evaluatePolicy( kStimulusDisplayWranglerWake );
7099 	}
7100 #endif /* DISPLAY_WRANGLER_PRESENT */
7101 }
7102 
7103 //******************************************************************************
7104 // User active state management
7105 //******************************************************************************
7106 
7107 void
7108 IOPMrootDomain::preventTransitionToUserActive( bool prevent )
7109 {
7110 #if DISPLAY_WRANGLER_PRESENT
7111 	_preventUserActive = prevent;
7112 	if (wrangler && !_preventUserActive) {
7113 		// Allowing transition to user active, but the wrangler may have
7114 		// already powered ON in case of sleep cancel/revert. Poll the
7115 		// same conditions checked for in displayWranglerNotification()
7116 		// to bring the user active state up to date.
7117 
7118 		if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
7119 		    (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
7120 		    kWranglerPowerStateMax)) {
7121 			evaluatePolicy( kStimulusEnterUserActiveState );
7122 		}
7123 	}
7124 #endif /* DISPLAY_WRANGLER_PRESENT */
7125 }
7126 
7127 //******************************************************************************
7128 // Approve usage of delayed child notification by PM.
7129 //******************************************************************************
7130 
7131 bool
7132 IOPMrootDomain::shouldDelayChildNotification(
7133 	IOService * service )
7134 {
7135 	if ((kFullWakeReasonNone == fullWakeReason) &&
7136 	    (kSystemTransitionWake == _systemTransitionType)) {
7137 		DLOG("%s: delay child notify\n", service->getName());
7138 		return true;
7139 	}
7140 	return false;
7141 }
7142 
7143 //******************************************************************************
7144 // PM actions for PCI device.
7145 //******************************************************************************
7146 
7147 void
7148 IOPMrootDomain::handlePowerChangeStartForPCIDevice(
7149 	IOService *             service,
7150 	IOPMActions *           actions,
7151 	const IOPMRequest *     request,
7152 	IOPMPowerStateIndex     powerState,
7153 	IOPMPowerChangeFlags *  inOutChangeFlags )
7154 {
7155 	pmTracer->tracePCIPowerChange(
7156 		PMTraceWorker::kPowerChangeStart,
7157 		service, *inOutChangeFlags,
7158 		(actions->flags & kPMActionsPCIBitNumberMask));
7159 }
7160 
7161 void
7162 IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
7163 	IOService *             service,
7164 	IOPMActions *           actions,
7165 	const IOPMRequest *     request,
7166 	IOPMPowerStateIndex     powerState,
7167 	IOPMPowerChangeFlags    changeFlags )
7168 {
7169 	pmTracer->tracePCIPowerChange(
7170 		PMTraceWorker::kPowerChangeCompleted,
7171 		service, changeFlags,
7172 		(actions->flags & kPMActionsPCIBitNumberMask));
7173 }
7174 
7175 //******************************************************************************
7176 // registerInterest
7177 //
7178 // Override IOService::registerInterest() for root domain clients.
7179 //******************************************************************************
7180 
7181 class IOPMServiceInterestNotifier : public _IOServiceInterestNotifier
7182 {
7183 	friend class IOPMrootDomain;
7184 	OSDeclareDefaultStructors(IOPMServiceInterestNotifier);
7185 
7186 protected:
7187 	uint32_t        ackTimeoutCnt;
7188 	uint32_t        msgType;    // Last type seen by the message filter
7189 	uint32_t        lastSleepWakeMsgType;
7190 	uint32_t        msgIndex;
7191 	uint32_t        maxMsgDelayMS;
7192 	uint32_t        maxAckDelayMS;
7193 	uint64_t        msgAbsTime;
7194 	uint64_t        uuid0;
7195 	uint64_t        uuid1;
7196 	OSSharedPtr<const OSSymbol> identifier;
7197 	OSSharedPtr<const OSSymbol> clientName;
7198 };
7199 
7200 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
7201 
7202 OSSharedPtr<IONotifier>
7203 IOPMrootDomain::registerInterest(
7204 	const OSSymbol * typeOfInterest,
7205 	IOServiceInterestHandler handler,
7206 	void * target, void * ref )
7207 {
7208 	IOPMServiceInterestNotifier* notifier;
7209 	bool            isSystemCapabilityClient;
7210 	bool            isKernelCapabilityClient;
7211 	IOReturn        rc = kIOReturnError;
7212 
7213 	isSystemCapabilityClient = typeOfInterest &&
7214 	    typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
7215 
7216 	isKernelCapabilityClient = typeOfInterest &&
7217 	    typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
7218 
7219 	if (isSystemCapabilityClient) {
7220 		typeOfInterest = gIOAppPowerStateInterest;
7221 	}
7222 
7223 	notifier = new IOPMServiceInterestNotifier;
7224 	if (!notifier) {
7225 		return NULL;
7226 	}
7227 
7228 	if (notifier->init()) {
7229 		rc  = super::registerInterestForNotifier(notifier, typeOfInterest, handler, target, ref);
7230 	}
7231 	if (rc != kIOReturnSuccess) {
7232 		OSSafeReleaseNULL(notifier);
7233 		return NULL;
7234 	}
7235 
7236 	notifier->ackTimeoutCnt = 0;
7237 
7238 	if (pmPowerStateQueue) {
7239 		if (isSystemCapabilityClient) {
7240 			notifier->retain();
7241 			if (pmPowerStateQueue->submitPowerEvent(
7242 				    kPowerEventRegisterSystemCapabilityClient, notifier) == false) {
7243 				notifier->release();
7244 			}
7245 		}
7246 
7247 		if (isKernelCapabilityClient) {
7248 			notifier->retain();
7249 			if (pmPowerStateQueue->submitPowerEvent(
7250 				    kPowerEventRegisterKernelCapabilityClient, notifier) == false) {
7251 				notifier->release();
7252 			}
7253 		}
7254 	}
7255 
7256 	OSSharedPtr<OSData> data;
7257 	uint8_t *uuid = NULL;
7258 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithAddress((vm_address_t)handler);
7259 	if (kext) {
7260 		data = kext->copyUUID();
7261 	}
7262 	if (data && (data->getLength() == sizeof(uuid_t))) {
7263 		uuid = (uint8_t *)(data->getBytesNoCopy());
7264 
7265 		notifier->uuid0 = ((uint64_t)(uuid[0]) << 56) | ((uint64_t)(uuid[1]) << 48) | ((uint64_t)(uuid[2]) << 40) |
7266 		    ((uint64_t)(uuid[3]) << 32) | ((uint64_t)(uuid[4]) << 24) | ((uint64_t)(uuid[5]) << 16) |
7267 		    ((uint64_t)(uuid[6]) << 8) | (uuid[7]);
7268 		notifier->uuid1 = ((uint64_t)(uuid[8]) << 56) | ((uint64_t)(uuid[9]) << 48) | ((uint64_t)(uuid[10]) << 40) |
7269 		    ((uint64_t)(uuid[11]) << 32) | ((uint64_t)(uuid[12]) << 24) | ((uint64_t)(uuid[13]) << 16) |
7270 		    ((uint64_t)(uuid[14]) << 8) | (uuid[15]);
7271 
7272 		notifier->identifier = copyKextIdentifierWithAddress((vm_address_t) handler);
7273 	}
7274 	return OSSharedPtr<IOPMServiceInterestNotifier>(notifier, OSNoRetain);
7275 }
7276 
7277 //******************************************************************************
7278 // systemMessageFilter
7279 //
7280 //******************************************************************************
7281 
7282 bool
7283 IOPMrootDomain::systemMessageFilter(
7284 	void * object, void * arg1, void * arg2, void * arg3 )
7285 {
7286 	const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
7287 	bool  isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
7288 	bool  isCapPowerd = (object == (void *) systemCapabilityNotifier.get());
7289 	bool  isCapClient = false;
7290 	bool  allow = false;
7291 	OSBoolean **waitForReply = (typeof(waitForReply))arg3;
7292 	IOPMServiceInterestNotifier *notifier;
7293 
7294 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object);
7295 
7296 	do {
7297 		// When powerd and kernel priority clients register capability interest,
7298 		// the power tree is sync'ed to inform those clients about the current
7299 		// system capability. Only allow capability change messages during sync.
7300 		if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
7301 		    (!isCapMsg || !_joinedCapabilityClients ||
7302 		    !_joinedCapabilityClients->containsObject((OSObject *) object))) {
7303 			break;
7304 		}
7305 
7306 		// Capability change message for powerd and kernel clients
7307 		if (isCapMsg) {
7308 			// Kernel priority clients
7309 			if ((context->notifyType == kNotifyPriority) ||
7310 			    (context->notifyType == kNotifyCapabilityChangePriority)) {
7311 				isCapClient = true;
7312 			}
7313 
7314 			// powerd will maintain two client registrations with root domain.
7315 			// isCapPowerd will be TRUE for any message targeting the powerd
7316 			// exclusive (capability change) interest registration.
7317 			if (isCapPowerd && (context->notifyType == kNotifyCapabilityChangeApps)) {
7318 				isCapClient = true;
7319 			}
7320 		}
7321 
7322 		if (isCapClient) {
7323 			IOPMSystemCapabilityChangeParameters * capArgs =
7324 			    (IOPMSystemCapabilityChangeParameters *) arg2;
7325 
7326 			if (kSystemTransitionNewCapClient == _systemTransitionType) {
7327 				capArgs->fromCapabilities = 0;
7328 				capArgs->toCapabilities = _currentCapability;
7329 				capArgs->changeFlags = 0;
7330 			} else {
7331 				capArgs->fromCapabilities = _currentCapability;
7332 				capArgs->toCapabilities = _pendingCapability;
7333 
7334 				if (context->isPreChange) {
7335 					capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
7336 				} else {
7337 					capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
7338 				}
7339 
7340 				if (isCapPowerd && context->isPreChange) {
7341 					toldPowerdCapWillChange = true;
7342 				}
7343 			}
7344 
7345 			// App level capability change messages must only go to powerd.
7346 			// Wait for response post-change if capabilitiy is increasing.
7347 			// Wait for response pre-change if capability is decreasing.
7348 
7349 			if ((context->notifyType == kNotifyCapabilityChangeApps) && waitForReply &&
7350 			    ((capabilityLoss && context->isPreChange) ||
7351 			    (!capabilityLoss && !context->isPreChange))) {
7352 				*waitForReply = kOSBooleanTrue;
7353 			}
7354 
7355 			allow = true;
7356 			break;
7357 		}
7358 
7359 		// powerd will always receive CanSystemSleep, even for a demand sleep.
7360 		// It will also have a final chance to veto sleep after all clients
7361 		// have responded to SystemWillSleep
7362 
7363 		if ((kIOMessageCanSystemSleep == context->messageType) ||
7364 		    (kIOMessageSystemWillNotSleep == context->messageType)) {
7365 			if (isCapPowerd) {
7366 				allow = true;
7367 				break;
7368 			}
7369 
7370 			// Demand sleep, don't ask apps for permission
7371 			if (context->changeFlags & kIOPMSkipAskPowerDown) {
7372 				break;
7373 			}
7374 		}
7375 
7376 		if (kIOPMMessageLastCallBeforeSleep == context->messageType) {
7377 			if (isCapPowerd && CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
7378 			    (fullToDarkReason == kIOPMSleepReasonIdle)) {
7379 				allow = true;
7380 			}
7381 			break;
7382 		}
7383 
7384 		// Drop capability change messages for legacy clients.
7385 		// Drop legacy system sleep messages for powerd capability interest.
7386 		if (isCapMsg || isCapPowerd) {
7387 			break;
7388 		}
7389 
7390 		// Not a capability change message.
7391 		// Perform message filtering based on _systemMessageClientMask.
7392 
7393 		if ((context->notifyType == kNotifyApps) &&
7394 		    (_systemMessageClientMask & kSystemMessageClientLegacyApp)) {
7395 			if (!notifier) {
7396 				break;
7397 			}
7398 
7399 			if ((notifier->lastSleepWakeMsgType == context->messageType) &&
7400 			    (notifier->lastSleepWakeMsgType == kIOMessageSystemWillPowerOn)) {
7401 				break; // drop any duplicate WillPowerOn for AOT devices
7402 			}
7403 
7404 			allow = true;
7405 
7406 			if (waitForReply) {
7407 				if (notifier->ackTimeoutCnt >= 3) {
7408 					*waitForReply = kOSBooleanFalse;
7409 				} else {
7410 					*waitForReply = kOSBooleanTrue;
7411 				}
7412 			}
7413 		} else if ((context->notifyType == kNotifyPriority) &&
7414 		    (_systemMessageClientMask & kSystemMessageClientKernel)) {
7415 			allow = true;
7416 		}
7417 
7418 		// Check sleep/wake message ordering
7419 		if (allow) {
7420 			if (context->messageType == kIOMessageSystemWillSleep ||
7421 			    context->messageType == kIOMessageSystemWillPowerOn ||
7422 			    context->messageType == kIOMessageSystemHasPoweredOn) {
7423 				notifier->lastSleepWakeMsgType = context->messageType;
7424 			}
7425 		}
7426 	} while (false);
7427 
7428 	if (allow && isCapMsg && _joinedCapabilityClients) {
7429 		_joinedCapabilityClients->removeObject((OSObject *) object);
7430 		if (_joinedCapabilityClients->getCount() == 0) {
7431 			DMSG("destroyed capability client set %p\n",
7432 			    OBFUSCATE(_joinedCapabilityClients.get()));
7433 			_joinedCapabilityClients.reset();
7434 		}
7435 	}
7436 	if (notifier) {
7437 		// Record the last seen message type even if the message is dropped
7438 		// for traceFilteredNotification().
7439 		notifier->msgType = context->messageType;
7440 	}
7441 
7442 	return allow;
7443 }
7444 
7445 //******************************************************************************
7446 // setMaintenanceWakeCalendar
7447 //
7448 //******************************************************************************
7449 
7450 IOReturn
7451 IOPMrootDomain::setMaintenanceWakeCalendar(
7452 	const IOPMCalendarStruct * calendar )
7453 {
7454 	OSSharedPtr<OSData> data;
7455 	IOReturn ret = 0;
7456 
7457 	if (!calendar) {
7458 		return kIOReturnBadArgument;
7459 	}
7460 
7461 	data = OSData::withValue(*calendar);
7462 	if (!data) {
7463 		return kIOReturnNoMemory;
7464 	}
7465 
7466 	if (kPMCalendarTypeMaintenance == calendar->selector) {
7467 		ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey.get(), data.get());
7468 	} else if (kPMCalendarTypeSleepService == calendar->selector) {
7469 		ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey.get(), data.get());
7470 	}
7471 
7472 	return ret;
7473 }
7474 
7475 // MARK: -
7476 // MARK: Display Wrangler
7477 
7478 //******************************************************************************
7479 // displayWranglerNotification
7480 //
7481 // Handle the notification when the IODisplayWrangler changes power state.
7482 //******************************************************************************
7483 
7484 IOReturn
7485 IOPMrootDomain::displayWranglerNotification(
7486 	void * target, void * refCon,
7487 	UInt32 messageType, IOService * service,
7488 	void * messageArgument, vm_size_t argSize )
7489 {
7490 #if DISPLAY_WRANGLER_PRESENT
7491 	IOPMPowerStateIndex                 displayPowerState;
7492 	IOPowerStateChangeNotification *    params =
7493 	    (IOPowerStateChangeNotification *) messageArgument;
7494 
7495 	if ((messageType != kIOMessageDeviceWillPowerOff) &&
7496 	    (messageType != kIOMessageDeviceHasPoweredOn)) {
7497 		return kIOReturnUnsupported;
7498 	}
7499 
7500 	ASSERT_GATED();
7501 	if (!gRootDomain) {
7502 		return kIOReturnUnsupported;
7503 	}
7504 
7505 	displayPowerState = params->stateNumber;
7506 	DLOG("wrangler %s ps %d\n",
7507 	    getIOMessageString(messageType), (uint32_t) displayPowerState);
7508 
7509 	switch (messageType) {
7510 	case kIOMessageDeviceWillPowerOff:
7511 		// Display wrangler has dropped power due to display idle
7512 		// or force system sleep.
7513 		//
7514 		// 4 Display ON             kWranglerPowerStateMax
7515 		// 3 Display Dim            kWranglerPowerStateDim
7516 		// 2 Display Sleep          kWranglerPowerStateSleep
7517 		// 1 Not visible to user
7518 		// 0 Not visible to user    kWranglerPowerStateMin
7519 
7520 		if (displayPowerState <= kWranglerPowerStateSleep) {
7521 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
7522 		}
7523 		break;
7524 
7525 	case kIOMessageDeviceHasPoweredOn:
7526 		// Display wrangler has powered on due to user activity
7527 		// or wake from sleep.
7528 
7529 		if (kWranglerPowerStateMax == displayPowerState) {
7530 			gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
7531 
7532 			// See comment in handleUpdatePowerClientForDisplayWrangler
7533 			if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
7534 			    kWranglerPowerStateMax) {
7535 				gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
7536 			}
7537 		}
7538 		break;
7539 	}
7540 #endif /* DISPLAY_WRANGLER_PRESENT */
7541 	return kIOReturnUnsupported;
7542 }
7543 
7544 //******************************************************************************
7545 // reportUserInput
7546 //
7547 //******************************************************************************
7548 
7549 void
7550 IOPMrootDomain::updateUserActivity( void )
7551 {
7552 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7553 	clock_get_uptime(&userActivityTime);
7554 	bool aborting =  ((lastSleepReason == kIOPMSleepReasonSoftware)
7555 	    || (lastSleepReason == kIOPMSleepReasonIdle)
7556 	    || (lastSleepReason == kIOPMSleepReasonMaintenance));
7557 	if (aborting) {
7558 		userActivityCount++;
7559 		DLOG("user activity reported %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
7560 	}
7561 #endif
7562 }
7563 void
7564 IOPMrootDomain::reportUserInput( void )
7565 {
7566 	if (wrangler) {
7567 		wrangler->activityTickle(0, 0);
7568 	}
7569 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
7570 	// Update user activity
7571 	updateUserActivity();
7572 
7573 	if (!darkWakeExit && ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0)) {
7574 		// update user active abs time
7575 		clock_get_uptime(&gUserActiveAbsTime);
7576 		pmPowerStateQueue->submitPowerEvent(
7577 			kPowerEventPolicyStimulus,
7578 			(void *) kStimulusDarkWakeActivityTickle,
7579 			true /* set wake type */ );
7580 	}
7581 #endif
7582 }
7583 
7584 void
7585 IOPMrootDomain::requestUserActive(IOService *device, const char *reason)
7586 {
7587 #if DISPLAY_WRANGLER_PRESENT
7588 	if (wrangler) {
7589 		wrangler->activityTickle(0, 0);
7590 	}
7591 #else
7592 	if (!device) {
7593 		DLOG("requestUserActive: device is null\n");
7594 		return;
7595 	}
7596 	OSSharedPtr<const OSSymbol> deviceName = device->copyName();
7597 	uint64_t registryID = device->getRegistryEntryID();
7598 
7599 	if (!deviceName || !registryID) {
7600 		DLOG("requestUserActive: no device name or registry entry\n");
7601 		return;
7602 	}
7603 	const char *name = deviceName->getCStringNoCopy();
7604 	char payload[128];
7605 	snprintf(payload, sizeof(payload), "%s:%s", name, reason);
7606 	DLOG("requestUserActive from %s (0x%llx) for %s\n", name, registryID, reason);
7607 	messageClient(kIOPMMessageRequestUserActive, systemCapabilityNotifier.get(), (void *)payload, sizeof(payload));
7608 #endif
7609 }
7610 
7611 //******************************************************************************
7612 // latchDisplayWranglerTickle
7613 //******************************************************************************
7614 
7615 bool
7616 IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
7617 {
7618 #if DISPLAY_WRANGLER_PRESENT
7619 	if (latch) {
7620 		if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
7621 		    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
7622 		    !checkSystemCanSustainFullWake()) {
7623 			// Currently in dark wake, and not transitioning to full wake.
7624 			// Full wake is unsustainable, so latch the tickle to prevent
7625 			// the display from lighting up momentarily.
7626 			wranglerTickled = true;
7627 		} else {
7628 			wranglerTickled = false;
7629 		}
7630 	} else if (wranglerTickled && checkSystemCanSustainFullWake()) {
7631 		wranglerTickled = false;
7632 
7633 		pmPowerStateQueue->submitPowerEvent(
7634 			kPowerEventPolicyStimulus,
7635 			(void *) kStimulusDarkWakeActivityTickle );
7636 	}
7637 
7638 	return wranglerTickled;
7639 #else  /* ! DISPLAY_WRANGLER_PRESENT */
7640 	return false;
7641 #endif /* ! DISPLAY_WRANGLER_PRESENT */
7642 }
7643 
7644 //******************************************************************************
7645 // setDisplayPowerOn
7646 //
7647 // For root domain user client
7648 //******************************************************************************
7649 
7650 void
7651 IOPMrootDomain::setDisplayPowerOn( uint32_t options )
7652 {
7653 	pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
7654 	    (void *) NULL, options );
7655 }
7656 
7657 // MARK: -
7658 // MARK: System PM Policy
7659 
7660 //******************************************************************************
7661 // checkSystemSleepAllowed
7662 //
7663 //******************************************************************************
7664 
7665 bool
7666 IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
7667     uint32_t     sleepReason )
7668 {
7669 	uint32_t err = 0;
7670 
7671 	// Conditions that prevent idle and demand system sleep.
7672 
7673 	do {
7674 		if (gSleepDisabledFlag) {
7675 			err = kPMConfigPreventSystemSleep;
7676 			break;
7677 		}
7678 
7679 		if (userDisabledAllSleep) {
7680 			err = kPMUserDisabledAllSleep; // 1. user-space sleep kill switch
7681 			break;
7682 		}
7683 
7684 		if (systemBooting || systemShutdown || gWillShutdown) {
7685 			err = kPMSystemRestartBootingInProgress; // 2. restart or shutdown in progress
7686 			break;
7687 		}
7688 
7689 		if (options == 0) {
7690 			break;
7691 		}
7692 
7693 		// Conditions above pegs the system at full wake.
7694 		// Conditions below prevent system sleep but does not prevent
7695 		// dark wake, and must be called from gated context.
7696 
7697 #if !CONFIG_SLEEP
7698 		err = kPMConfigPreventSystemSleep;    // 3. config does not support sleep
7699 		break;
7700 #endif
7701 
7702 		if (_driverKitMatchingAssertionCount != 0 || _driverKitSyncedAssertionCount != 0) {
7703 			err = kPMCPUAssertion;
7704 			break;
7705 		}
7706 
7707 		// Check for any dexts currently being added to the PM tree. Sleeping while
7708 		// this is in flight can cause IOServicePH to timeout.
7709 		if (!IOServicePH::checkPMReady()) {
7710 #if !defined(XNU_TARGET_OS_OSX)
7711 			if (!(lowBatteryCondition || thermalWarningState || thermalEmergencyState)) {
7712 				// 116893363: kPMDKNotReady sleep cancellations often leaves embedded devices
7713 				// in dark wake for long periods of time, which causes issues as apps were
7714 				// already informed of sleep during the f->9 transition. As a temporary
7715 				// measure, always full wake if we hit this specific condition.
7716 				pmPowerStateQueue->submitPowerEvent(
7717 					kPowerEventPolicyStimulus,
7718 					(void *) kStimulusDarkWakeActivityTickle);
7719 			}
7720 #endif
7721 			err = kPMDKNotReady;
7722 			break;
7723 		}
7724 
7725 		if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7726 			break; // always sleep on low battery or when in thermal warning/emergency state
7727 		}
7728 
7729 		if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency) {
7730 			break; // always sleep on dark wake thermal emergencies
7731 		}
7732 
7733 		if (preventSystemSleepList->getCount() != 0) {
7734 			err = kPMChildPreventSystemSleep; // 4. child prevent system sleep clamp
7735 			break;
7736 		}
7737 
7738 
7739 		if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
7740 		    kIOPMDriverAssertionLevelOn) {
7741 			err = kPMCPUAssertion; // 5. CPU assertion
7742 			break;
7743 		}
7744 
7745 		if (pciCantSleepValid) {
7746 			if (pciCantSleepFlag) {
7747 				err = kPMPCIUnsupported; // 6. PCI card does not support PM (cached)
7748 			}
7749 			break;
7750 		} else if (sleepSupportedPEFunction &&
7751 		    CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
7752 			IOReturn ret;
7753 			OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
7754 			ret = getPlatform()->callPlatformFunction(
7755 				sleepSupportedPEFunction.get(), false,
7756 				NULL, NULL, NULL, NULL);
7757 			pciCantSleepValid = true;
7758 			pciCantSleepFlag  = false;
7759 			if ((platformSleepSupport & kPCICantSleep) ||
7760 			    ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported))) {
7761 				err = 6; // 6. PCI card does not support PM
7762 				pciCantSleepFlag = true;
7763 				break;
7764 			}
7765 		}
7766 	}while (false);
7767 
7768 	if (err) {
7769 		DLOG("System sleep prevented by %s\n", getSystemSleepPreventerString(err));
7770 		return false;
7771 	}
7772 	return true;
7773 }
7774 
7775 bool
7776 IOPMrootDomain::checkSystemSleepEnabled( void )
7777 {
7778 	return checkSystemSleepAllowed(0, 0);
7779 }
7780 
7781 bool
7782 IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
7783 {
7784 	ASSERT_GATED();
7785 	return checkSystemSleepAllowed(1, sleepReason);
7786 }
7787 
7788 //******************************************************************************
7789 // checkSystemCanSustainFullWake
7790 //******************************************************************************
7791 
7792 bool
7793 IOPMrootDomain::checkSystemCanSustainFullWake( void )
7794 {
7795 	if (lowBatteryCondition || thermalWarningState || thermalEmergencyState) {
7796 		// Low battery wake, or received a low battery notification
7797 		// while system is awake. This condition will persist until
7798 		// the following wake.
7799 		return false;
7800 	}
7801 
7802 	if (clamshellExists && clamshellClosed && !clamshellSleepDisableMask) {
7803 		// Graphics state is unknown and external display might not be probed.
7804 		// Do not incorporate state that requires graphics to be in max power
7805 		// such as desktopMode or clamshellDisabled.
7806 
7807 		if (!acAdaptorConnected) {
7808 			DLOG("full wake check: no AC\n");
7809 			return false;
7810 		}
7811 	}
7812 	return true;
7813 }
7814 
7815 //******************************************************************************
7816 // checkSystemCanAbortIdleSleep
7817 //******************************************************************************
7818 
7819 bool
7820 IOPMrootDomain::checkSystemCanAbortIdleSleep( void )
7821 {
7822 	bool abortableSleepType =  ((lastSleepReason == kIOPMSleepReasonIdle)
7823 	    || (lastSleepReason == 0));
7824 	return idleSleepRevertible && abortableSleepType;
7825 }
7826 
7827 //******************************************************************************
7828 // considerRunMode
7829 // consider the driver for AOT power on via the runmode mask
7830 //******************************************************************************
7831 
7832 int32_t
7833 IOPMrootDomain::considerRunMode(IOService * service, uint64_t pmDriverClass)
7834 {
7835 	int32_t promote;
7836 
7837 	if ((0 == _aotRunMode) || (service == this)) {
7838 		// neutral
7839 		return 0;
7840 	}
7841 	promote = (0 != (_aotRunMode & pmDriverClass)) ? 1 : -1;
7842 	if (promote > 0) {
7843 		IOLog("IOPMRD: %s 0x%llx runmode to %s\n", service->getName(), pmDriverClass, (promote < 0) ? "OFF" : "ON");
7844 	}
7845 	return promote;
7846 }
7847 
7848 //******************************************************************************
7849 // attemptIdleSleepAbort
7850 //******************************************************************************
7851 
7852 bool
7853 IOPMrootDomain::attemptIdleSleepAbort( void )
7854 {
7855 	if (!gIOPMWorkLoop->inGate()) {
7856 		bool ret = gIOPMWorkLoop->runAction(
7857 			OSMemberFunctionCast(IOWorkLoop::Action, this,
7858 			&IOPMrootDomain::attemptIdleSleepAbort),
7859 			this);
7860 		return ret;
7861 	}
7862 
7863 	bool canAbort = checkSystemCanAbortIdleSleep();
7864 	if (canAbort) {
7865 		cancelIdlePowerDownSync();
7866 	} else if (lastSleepReason == kIOPMSleepReasonIdle) {
7867 		scheduleImmediateDebugWake();
7868 	}
7869 
7870 	return canAbort;
7871 }
7872 
7873 //******************************************************************************
7874 // setIdleSleepRevertible
7875 //******************************************************************************
7876 
7877 void
7878 IOPMrootDomain::setIdleSleepRevertible( bool revertible )
7879 {
7880 	idleSleepRevertible = revertible;
7881 }
7882 
7883 //******************************************************************************
7884 // mustHibernate
7885 //******************************************************************************
7886 
7887 #if HIBERNATION
7888 
7889 bool
7890 IOPMrootDomain::mustHibernate( void )
7891 {
7892 	return lowBatteryCondition || thermalWarningState;
7893 }
7894 
7895 #endif /* HIBERNATION */
7896 
7897 //******************************************************************************
7898 // AOT
7899 //******************************************************************************
7900 
7901 // Tables for accumulated days in year by month, latter used for leap years
7902 
7903 static const unsigned int daysbymonth[] =
7904 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
7905 
7906 static const unsigned int lydaysbymonth[] =
7907 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
7908 
7909 static int __unused
7910 IOPMConvertSecondsToCalendar(clock_sec_t secs, IOPMCalendarStruct * dt)
7911 {
7912 	const unsigned int *    dbm = daysbymonth;
7913 	clock_sec_t             n, x, y, z;
7914 
7915 	// Calculate seconds, minutes and hours
7916 
7917 	n = secs % (24 * 3600);
7918 	dt->second = n % 60;
7919 	n /= 60;
7920 	dt->minute = n % 60;
7921 	dt->hour = (typeof(dt->hour))(n / 60);
7922 
7923 	// Calculate day of week
7924 
7925 	n = secs / (24 * 3600);
7926 //	dt->dayWeek = (n + 4) % 7;
7927 
7928 	// Calculate year
7929 	// Rebase from days since Unix epoch (1/1/1970) store in 'n',
7930 	// to days since 1/1/1968 to start on 4 year cycle, beginning
7931 	// on a leap year.
7932 
7933 	n += (366 + 365);
7934 
7935 	// Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
7936 	// Valid before 2100, since 2100 is not a leap year.
7937 
7938 	x = n / 1461;       // number of 4 year cycles
7939 	y = n % 1461;       // days into current 4 year cycle
7940 	z = 1968 + (4 * x);
7941 
7942 	// Add in years in the current 4 year cycle
7943 
7944 	if (y >= 366) {
7945 		y -= 366;   // days after the leap year
7946 		n = y % 365; // days into the current year
7947 		z += (1 + y / 365); // years after the past 4-yr cycle
7948 	} else {
7949 		n = y;
7950 		dbm = lydaysbymonth;
7951 	}
7952 	if (z > 2099) {
7953 		return 0;
7954 	}
7955 
7956 	dt->year = (typeof(dt->year))z;
7957 
7958 	// Adjust remaining days value to start at 1
7959 
7960 	n += 1;
7961 
7962 	// Calculate month
7963 
7964 	for (x = 1; (n > dbm[x]) && (x < 12); x++) {
7965 		continue;
7966 	}
7967 	dt->month = (typeof(dt->month))x;
7968 
7969 	// Calculate day of month
7970 
7971 	dt->day = (typeof(dt->day))(n - dbm[x - 1]);
7972 
7973 	return 1;
7974 }
7975 
7976 static clock_sec_t
7977 IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
7978 {
7979 	const unsigned int *    dbm = daysbymonth;
7980 	long                    y, secs, days;
7981 
7982 	if (dt->year < 1970 || dt->month > 12) {
7983 		return 0;
7984 	}
7985 
7986 	// Seconds elapsed in the current day
7987 
7988 	secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
7989 
7990 	// Number of days from 1/1/70 to beginning of current year
7991 	// Account for extra day every 4 years starting at 1973
7992 
7993 	y = dt->year - 1970;
7994 	days = (y * 365) + ((y + 1) / 4);
7995 
7996 	// Change table if current year is a leap year
7997 
7998 	if ((dt->year % 4) == 0) {
7999 		dbm = lydaysbymonth;
8000 	}
8001 
8002 	// Add in days elapsed in the current year
8003 
8004 	days += (dt->day - 1) + dbm[dt->month - 1];
8005 
8006 	// Add accumulated days to accumulated seconds
8007 
8008 	secs += 24 * 3600 * days;
8009 
8010 	return secs;
8011 }
8012 
8013 unsigned long
8014 IOPMrootDomain::getRUN_STATE(void)
8015 {
8016 	return (_aotNow && !(kIOPMWakeEventAOTExitFlags & _aotPendingFlags)) ? AOT_STATE : ON_STATE;
8017 }
8018 
8019 bool
8020 IOPMrootDomain::isAOTMode()
8021 {
8022 	return _aotNow;
8023 }
8024 
8025 bool
8026 IOPMrootDomain::isLPWMode()
8027 {
8028 	return gLPWFlags && currentOrPendingPowerState(AOT_STATE);
8029 }
8030 
8031 bool
8032 IOPMIsAOTMode(void)
8033 {
8034 	return gIOPMRootDomain && gIOPMRootDomain->isAOTMode();
8035 }
8036 bool
8037 IOPMIsLPWMode(void)
8038 {
8039 	return gIOPMRootDomain && gIOPMRootDomain->isLPWMode();
8040 }
8041 
8042 void
8043 IOPMNetworkStackFullWake(uint64_t flags, const char * reason)
8044 {
8045 	assert(kIOPMNetworkStackFullWakeFlag == flags);
8046 	assert(gIOPMRootDomain);
8047 	gIOPMRootDomain->claimSystemWakeEvent(gIOPMRootDomain, kIOPMWakeEventAOTExit, reason, NULL);
8048 }
8049 
8050 IOReturn
8051 IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
8052 {
8053 	if (kIOPMAOTModeCycle & _aotMode) {
8054 		return kIOReturnSuccess;
8055 	}
8056 	return _setWakeTime(wakeContinuousTime);
8057 }
8058 
8059 IOReturn
8060 IOPMrootDomain::_setWakeTime(uint64_t wakeContinuousTime)
8061 {
8062 	clock_sec_t     nowsecs, wakesecs;
8063 	clock_usec_t    nowmicrosecs, wakemicrosecs;
8064 	uint64_t        nowAbs, wakeAbs;
8065 
8066 	if (!_aotMode) {
8067 		return kIOReturnNotReady;
8068 	}
8069 
8070 	clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
8071 	wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
8072 	if (wakeAbs < nowAbs) {
8073 		printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
8074 		wakeAbs = nowAbs;
8075 	}
8076 	wakeAbs -= nowAbs;
8077 	absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
8078 
8079 	wakesecs += nowsecs;
8080 	wakemicrosecs += nowmicrosecs;
8081 	if (wakemicrosecs >= USEC_PER_SEC) {
8082 		wakesecs++;
8083 		wakemicrosecs -= USEC_PER_SEC;
8084 	}
8085 	if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
8086 		wakesecs++;
8087 	}
8088 
8089 	IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
8090 
8091 	if (_aotWakeTimeContinuous != wakeContinuousTime) {
8092 		_aotWakeTimeContinuous = wakeContinuousTime;
8093 		IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
8094 	}
8095 	_aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
8096 	_aotWakeTimeUTC               = wakesecs;
8097 
8098 	return kIOReturnSuccess;
8099 }
8100 
8101 // assumes WAKEEVENT_LOCK
8102 bool
8103 IOPMrootDomain::aotShouldExit(bool software)
8104 {
8105 	bool exitNow = false;
8106 	const char * reason = "";
8107 
8108 	if (!_aotNow) {
8109 		return false;
8110 	}
8111 
8112 	if (software) {
8113 		exitNow = true;
8114 		_aotMetrics->softwareRequestCount++;
8115 		reason = "software request";
8116 	} else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
8117 		exitNow = true;
8118 		reason = gWakeReasonString;
8119 	} else if ((kIOPMAOTModeRespectTimers & _aotMode) && _calendarWakeAlarmUTC) {
8120 		clock_sec_t     sec;
8121 		clock_usec_t    usec;
8122 		clock_get_calendar_microtime(&sec, &usec);
8123 		if (_calendarWakeAlarmUTC <= sec) {
8124 			exitNow = true;
8125 			_aotMetrics->rtcAlarmsCount++;
8126 			reason = "user alarm";
8127 		}
8128 	}
8129 	if (exitNow) {
8130 		_aotPendingFlags |= kIOPMWakeEventAOTExit;
8131 		IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
8132 		    reason,
8133 		    _aotMetrics->sleepCount,
8134 		    _aotMetrics->possibleCount,
8135 		    _aotMetrics->confirmedPossibleCount,
8136 		    _aotMetrics->rejectedPossibleCount,
8137 		    _aotMetrics->expiredPossibleCount,
8138 		    _aotMetrics->noTimeSetCount,
8139 		    _aotMetrics->rtcAlarmsCount);
8140 	}
8141 	return exitNow;
8142 }
8143 
8144 void
8145 IOPMrootDomain::aotExit(bool cps)
8146 {
8147 	uint32_t savedMessageMask;
8148 
8149 	ASSERT_GATED();
8150 	_aotNow = false;
8151 	_aotRunMode = 0;
8152 	_aotReadyToFullWake = false;
8153 	if (_aotTimerScheduled) {
8154 		_aotTimerES->cancelTimeout();
8155 		_aotTimerScheduled = false;
8156 	}
8157 	updateTasksSuspend(kTasksSuspendNoChange, kTasksSuspendUnsuspended);
8158 
8159 	_aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
8160 	_aotLastWakeTime = 0;
8161 	if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
8162 		WAKEEVENT_LOCK();
8163 		strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
8164 		    gWakeReasonString,
8165 		    sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
8166 		WAKEEVENT_UNLOCK();
8167 	}
8168 
8169 	_aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
8170 
8171 	// Preserve the message mask since a system wake transition
8172 	// may have already started and initialized the mask.
8173 	savedMessageMask = _systemMessageClientMask;
8174 	_systemMessageClientMask = kSystemMessageClientLegacyApp;
8175 	tellClients(kIOMessageSystemWillPowerOn);
8176 	_systemMessageClientMask = savedMessageMask | kSystemMessageClientLegacyApp;
8177 
8178 	if (cps) {
8179 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAOTExit);
8180 	}
8181 }
8182 
8183 void
8184 IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
8185 {
8186 	bool exitNow;
8187 
8188 	IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
8189 
8190 	WAKEEVENT_LOCK();
8191 	exitNow = aotShouldExit(false);
8192 	if (timer != NULL) {
8193 		_aotTimerScheduled = false;
8194 	}
8195 	WAKEEVENT_UNLOCK();
8196 	if (exitNow) {
8197 		aotExit(true);
8198 	} else {
8199 #if 0
8200 		if (_aotLingerTime) {
8201 			uint64_t deadline;
8202 			IOLog("aot linger before sleep\n");
8203 			clock_absolutetime_interval_to_deadline(_aotLingerTime, &deadline);
8204 			clock_delay_until(deadline);
8205 		}
8206 #endif
8207 		privateSleepSystem(kIOPMSleepReasonSoftware);
8208 	}
8209 }
8210 
8211 //******************************************************************************
8212 // adjustPowerState
8213 //
8214 // Conditions that affect our wake/sleep decision has changed.
8215 // If conditions dictate that the system must remain awake, clamp power
8216 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
8217 // is TRUE, then remove the power clamp and allow the power state to drop
8218 // to SLEEP_STATE.
8219 //******************************************************************************
8220 
8221 void
8222 IOPMrootDomain::adjustPowerState( bool sleepASAP )
8223 {
8224 	DEBUG_LOG("adjustPowerState %s, asap %d, idleSleepEnabled %d, _aotNow %d\n",
8225 	    getPowerStateString((uint32_t) getPowerState()), sleepASAP, idleSleepEnabled, _aotNow);
8226 
8227 	ASSERT_GATED();
8228 
8229 	if (_aotNow) {
8230 		bool exitNow;
8231 
8232 		if (AOT_STATE != getPowerState()) {
8233 			return;
8234 		}
8235 		WAKEEVENT_LOCK();
8236 		exitNow = aotShouldExit(false);
8237 		if (!exitNow
8238 		    && !_aotTimerScheduled
8239 		    && (kIOPMWakeEventAOTPossibleExit == (kIOPMWakeEventAOTPossibleFlags & _aotPendingFlags))) {
8240 			_aotTimerScheduled = true;
8241 			_aotTimerES->setTimeout(_aotLingerTime, kMillisecondScale);
8242 		}
8243 		WAKEEVENT_UNLOCK();
8244 		if (exitNow) {
8245 			aotExit(true);
8246 		} else {
8247 			_aotReadyToFullWake = true;
8248 			if (!_aotTimerScheduled) {
8249 				if (kIOPMDriverAssertionLevelOn == getPMAssertionLevel(kIOPMDriverAssertionCPUBit)) {
8250 					// Don't try to force sleep during AOT while IOMobileFramebuffer is holding a power assertion.
8251 					// Doing so will result in the sleep being cancelled anyway,
8252 					// but this check avoids unnecessary thrashing in the power state engine.
8253 					return;
8254 				}
8255 				privateSleepSystem(kIOPMSleepReasonSoftware);
8256 			}
8257 		}
8258 		return;
8259 	}
8260 
8261 	if ((!idleSleepEnabled) || !checkSystemSleepEnabled()) {
8262 		changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonAdjustPowerState);
8263 	} else if (sleepASAP) {
8264 		changePowerStateWithTagToPriv(SLEEP_STATE, kCPSReasonAdjustPowerState);
8265 	}
8266 }
8267 
8268 void
8269 IOPMrootDomain::handleSetDisplayPowerOn(bool powerOn)
8270 {
8271 	if (powerOn) {
8272 		if (!checkSystemCanSustainFullWake()) {
8273 			DLOG("System cannot sustain full wake\n");
8274 			return;
8275 		}
8276 
8277 		// Force wrangler to max power state. If system is in dark wake
8278 		// this alone won't raise the wrangler's power state.
8279 		if (wrangler) {
8280 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
8281 		}
8282 
8283 		// System in dark wake, always requesting full wake should
8284 		// not have any bad side-effects, even if the request fails.
8285 
8286 		if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
8287 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
8288 			requestFullWake( kFullWakeReasonDisplayOn );
8289 		}
8290 	} else {
8291 		// Relenquish desire to power up display.
8292 		// Must first transition to state 1 since wrangler doesn't
8293 		// power off the displays at state 0. At state 0 the root
8294 		// domain is removed from the wrangler's power client list.
8295 		if (wrangler) {
8296 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
8297 			wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
8298 		}
8299 	}
8300 }
8301 
8302 TUNABLE(bool, test_sleep_in_vm, "test_sleep_in_vm", false);
8303 
8304 //******************************************************************************
8305 // dispatchPowerEvent
8306 //
8307 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
8308 //******************************************************************************
8309 
8310 void
8311 IOPMrootDomain::dispatchPowerEvent(
8312 	uint32_t event, void * arg0, uint64_t arg1 )
8313 {
8314 	ASSERT_GATED();
8315 
8316 	switch (event) {
8317 	case kPowerEventFeatureChanged:
8318 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8319 		messageClients(kIOPMMessageFeatureChange, this);
8320 		break;
8321 
8322 	case kPowerEventReceivedPowerNotification:
8323 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8324 		handlePowerNotification((UInt32)(uintptr_t) arg0 );
8325 		break;
8326 
8327 	case kPowerEventSystemBootCompleted:
8328 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8329 		if (systemBooting) {
8330 			systemBooting = false;
8331 
8332 			if (PE_get_default("sleep-disabled", &gSleepDisabledFlag, sizeof(gSleepDisabledFlag))) {
8333 				DLOG("Setting gSleepDisabledFlag to %u from device tree\n", gSleepDisabledFlag);
8334 				if (test_sleep_in_vm && gSleepDisabledFlag) {
8335 					DLOG("Clearing gSleepDisabledFlag due to test_sleep_in_vm boot-arg\n");
8336 					gSleepDisabledFlag = 0;
8337 				}
8338 			}
8339 
8340 			if (lowBatteryCondition || thermalEmergencyState) {
8341 				if (lowBatteryCondition) {
8342 					privateSleepSystem(kIOPMSleepReasonLowPower);
8343 				} else {
8344 					privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8345 				}
8346 				// The rest is unnecessary since the system is expected
8347 				// to sleep immediately. The following wake will update
8348 				// everything.
8349 				break;
8350 			}
8351 
8352 			sleepWakeDebugMemAlloc();
8353 			saveFailureData2File();
8354 
8355 			// If lid is closed, re-send lid closed notification
8356 			// now that booting is complete.
8357 			if (clamshellClosed) {
8358 				handlePowerNotification(kLocalEvalClamshellCommand);
8359 			}
8360 			evaluatePolicy( kStimulusAllowSystemSleepChanged );
8361 		}
8362 		break;
8363 
8364 	case kPowerEventSystemShutdown:
8365 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8366 		if (kOSBooleanTrue == (OSBoolean *) arg0) {
8367 			/* We set systemShutdown = true during shutdown
8368 			 *  to prevent sleep at unexpected times while loginwindow is trying
8369 			 *  to shutdown apps and while the OS is trying to transition to
8370 			 *  complete power of.
8371 			 *
8372 			 *  Set to true during shutdown, as soon as loginwindow shows
8373 			 *  the "shutdown countdown dialog", through individual app
8374 			 *  termination, and through black screen kernel shutdown.
8375 			 */
8376 			systemShutdown = true;
8377 		} else {
8378 			/*
8379 			 *  A shutdown was initiated, but then the shutdown
8380 			 *  was cancelled, clearing systemShutdown to false here.
8381 			 */
8382 			systemShutdown = false;
8383 		}
8384 		break;
8385 
8386 	case kPowerEventUserDisabledSleep:
8387 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8388 		userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
8389 		break;
8390 
8391 	case kPowerEventRegisterSystemCapabilityClient:
8392 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8393 
8394 		// reset() handles the arg0 == nullptr case for us
8395 		systemCapabilityNotifier.reset((IONotifier *) arg0, OSRetain);
8396 		/* intentional fall-through */
8397 		[[clang::fallthrough]];
8398 
8399 	case kPowerEventRegisterKernelCapabilityClient:
8400 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8401 		if (!_joinedCapabilityClients) {
8402 			_joinedCapabilityClients = OSSet::withCapacity(8);
8403 		}
8404 		if (arg0) {
8405 			OSSharedPtr<IONotifier> notify((IONotifier *) arg0, OSNoRetain);
8406 			if (_joinedCapabilityClients) {
8407 				_joinedCapabilityClients->setObject(notify.get());
8408 				synchronizePowerTree( kIOPMSyncNoChildNotify );
8409 			}
8410 		}
8411 		break;
8412 
8413 	case kPowerEventPolicyStimulus:
8414 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8415 		if (arg0) {
8416 			int stimulus = (int)(uintptr_t) arg0;
8417 			evaluatePolicy(stimulus, (uint32_t) arg1);
8418 		}
8419 		break;
8420 
8421 	case kPowerEventAssertionCreate:
8422 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8423 		if (pmAssertions) {
8424 			pmAssertions->handleCreateAssertion((OSValueObject<PMAssertStruct> *)arg0);
8425 		}
8426 		break;
8427 
8428 
8429 	case kPowerEventAssertionRelease:
8430 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8431 		if (pmAssertions) {
8432 			pmAssertions->handleReleaseAssertion(arg1);
8433 		}
8434 		break;
8435 
8436 	case kPowerEventAssertionSetLevel:
8437 		DMSG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8438 		if (pmAssertions) {
8439 			pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
8440 		}
8441 		break;
8442 
8443 	case kPowerEventQueueSleepWakeUUID:
8444 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8445 		handleQueueSleepWakeUUID((OSObject *)arg0);
8446 		break;
8447 	case kPowerEventPublishSleepWakeUUID:
8448 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8449 		handlePublishSleepWakeUUID((bool)arg0);
8450 		break;
8451 
8452 	case kPowerEventSetDisplayPowerOn:
8453 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8454 		if (arg1 != 0) {
8455 			displayPowerOnRequested = true;
8456 		} else {
8457 			displayPowerOnRequested = false;
8458 		}
8459 		handleSetDisplayPowerOn(displayPowerOnRequested);
8460 		break;
8461 
8462 	case kPowerEventPublishWakeType:
8463 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8464 
8465 		// Don't replace wake type property if already set
8466 		if ((arg0 == gIOPMWakeTypeUserKey) ||
8467 		    !propertyExists(kIOPMRootDomainWakeTypeKey)) {
8468 			const char * wakeType = NULL;
8469 
8470 			if (arg0 == gIOPMWakeTypeUserKey) {
8471 				requestUserActive(this, "WakeTypeUser");
8472 				wakeType = kIOPMRootDomainWakeTypeUser;
8473 			} else if (arg0 == gIOPMSettingDebugWakeRelativeKey) {
8474 				if (!(gDarkWakeFlags & kDarkWakeFlagAlarmIsDark)) {
8475 					requestUserActive(this, "WakeTypeAlarm");
8476 				}
8477 				wakeType = kIOPMRootDomainWakeTypeAlarm;
8478 			} else if (arg0 == gIOPMSettingSleepServiceWakeCalendarKey) {
8479 				darkWakeSleepService = true;
8480 				wakeType = kIOPMRootDomainWakeTypeSleepService;
8481 			} else if (arg0 == gIOPMSettingMaintenanceWakeCalendarKey) {
8482 				wakeType = kIOPMRootDomainWakeTypeMaintenance;
8483 			}
8484 
8485 			if (wakeType) {
8486 				setProperty(kIOPMRootDomainWakeTypeKey, wakeType);
8487 			}
8488 		}
8489 		break;
8490 
8491 	case kPowerEventAOTEvaluate:
8492 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8493 		if (_aotReadyToFullWake) {
8494 			aotEvaluate(NULL);
8495 		}
8496 		break;
8497 	case kPowerEventRunModeRequest:
8498 		DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
8499 		// arg1 == runModeMask
8500 		handleRequestRunMode(arg1);
8501 		break;
8502 	}
8503 }
8504 
8505 //******************************************************************************
8506 // systemPowerEventOccurred
8507 //
8508 // The power controller is notifying us of a hardware-related power management
8509 // event that we must handle.
8510 //
8511 // systemPowerEventOccurred covers the same functionality that
8512 // receivePowerNotification does; it simply provides a richer API for conveying
8513 // more information.
8514 //******************************************************************************
8515 
8516 IOReturn
8517 IOPMrootDomain::systemPowerEventOccurred(
8518 	const OSSymbol *event,
8519 	uint32_t intValue)
8520 {
8521 	IOReturn        attempt = kIOReturnSuccess;
8522 	OSSharedPtr<OSNumber>        newNumber;
8523 
8524 	if (!event) {
8525 		return kIOReturnBadArgument;
8526 	}
8527 
8528 	newNumber = OSNumber::withNumber(intValue, 8 * sizeof(intValue));
8529 	if (!newNumber) {
8530 		return kIOReturnInternalError;
8531 	}
8532 
8533 	attempt = systemPowerEventOccurred(event, static_cast<OSObject *>(newNumber.get()));
8534 
8535 	return attempt;
8536 }
8537 
8538 void
8539 IOPMrootDomain::setThermalState(OSObject *value)
8540 {
8541 	OSNumber * num;
8542 
8543 	if (gIOPMWorkLoop->inGate() == false) {
8544 		gIOPMWorkLoop->runAction(
8545 			OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setThermalState),
8546 			(OSObject *)this,
8547 			(void *)value);
8548 
8549 		return;
8550 	}
8551 	if (value && (num = OSDynamicCast(OSNumber, value))) {
8552 		thermalWarningState = ((num->unsigned32BitValue() == kIOPMThermalLevelWarning) ||
8553 		    (num->unsigned32BitValue() == kIOPMThermalLevelTrap)) ? 1 : 0;
8554 	}
8555 }
8556 
8557 IOReturn
8558 IOPMrootDomain::systemPowerEventOccurred(
8559 	const OSSymbol *event,
8560 	OSObject *value)
8561 {
8562 	OSSharedPtr<OSDictionary> thermalsDict;
8563 	bool shouldUpdate = true;
8564 
8565 	if (!event || !value) {
8566 		return kIOReturnBadArgument;
8567 	}
8568 
8569 	// LOCK
8570 	// We reuse featuresDict Lock because it already exists and guards
8571 	// the very infrequently used publish/remove feature mechanism; so there's zero rsk
8572 	// of stepping on that lock.
8573 	if (featuresDictLock) {
8574 		IOLockLock(featuresDictLock);
8575 	}
8576 
8577 	OSSharedPtr<OSObject> origThermalsProp = copyProperty(kIOPMRootDomainPowerStatusKey);
8578 	OSDictionary * origThermalsDict = OSDynamicCast(OSDictionary, origThermalsProp.get());
8579 
8580 	if (origThermalsDict) {
8581 		thermalsDict = OSDictionary::withDictionary(origThermalsDict);
8582 	} else {
8583 		thermalsDict = OSDictionary::withCapacity(1);
8584 	}
8585 
8586 	if (!thermalsDict) {
8587 		shouldUpdate = false;
8588 		goto exit;
8589 	}
8590 
8591 	thermalsDict->setObject(event, value);
8592 
8593 	setProperty(kIOPMRootDomainPowerStatusKey, thermalsDict.get());
8594 
8595 exit:
8596 	// UNLOCK
8597 	if (featuresDictLock) {
8598 		IOLockUnlock(featuresDictLock);
8599 	}
8600 
8601 	if (shouldUpdate) {
8602 		if (event &&
8603 		    event->isEqualTo(kIOPMThermalLevelWarningKey)) {
8604 			setThermalState(value);
8605 		}
8606 		messageClients(kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
8607 	}
8608 
8609 	return kIOReturnSuccess;
8610 }
8611 
8612 //******************************************************************************
8613 // receivePowerNotification
8614 //
8615 // The power controller is notifying us of a hardware-related power management
8616 // event that we must handle. This may be a result of an 'environment' interrupt
8617 // from the power mgt micro.
8618 //******************************************************************************
8619 
8620 IOReturn
8621 IOPMrootDomain::receivePowerNotification( UInt32 msg )
8622 {
8623 	if (msg & kIOPMPowerButton) {
8624 		uint32_t currentPhase = pmTracer->getTracePhase();
8625 		if (currentPhase != kIOPMTracePointSystemUp && currentPhase > kIOPMTracePointSystemSleep) {
8626 			DEBUG_LOG("power button pressed during wake. phase = %u\n", currentPhase);
8627 			swd_flags |= SWD_PWR_BTN_STACKSHOT;
8628 			thread_call_enter(powerButtonDown);
8629 		} else {
8630 			DEBUG_LOG("power button pressed when system is up\n");
8631 		}
8632 	} else if (msg & kIOPMPowerButtonUp) {
8633 		if (swd_flags & SWD_PWR_BTN_STACKSHOT) {
8634 			swd_flags &= ~SWD_PWR_BTN_STACKSHOT;
8635 			thread_call_enter(powerButtonUp);
8636 		}
8637 	} else {
8638 		pmPowerStateQueue->submitPowerEvent(
8639 			kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
8640 	}
8641 	return kIOReturnSuccess;
8642 }
8643 
8644 void
8645 IOPMrootDomain::handlePowerNotification( UInt32 msg )
8646 {
8647 	bool        eval_clamshell = false;
8648 	bool        eval_clamshell_alarm = false;
8649 
8650 	ASSERT_GATED();
8651 
8652 	/*
8653 	 * Local (IOPMrootDomain only) eval clamshell command
8654 	 */
8655 	if (msg & kLocalEvalClamshellCommand) {
8656 		if ((gClamshellFlags & kClamshell_WAR_47715679) && isRTCAlarmWake) {
8657 			eval_clamshell_alarm = true;
8658 
8659 			// reset isRTCAlarmWake. This evaluation should happen only once
8660 			// on RTC/Alarm wake. Any clamshell events after wake should follow
8661 			// the regular evaluation
8662 			isRTCAlarmWake = false;
8663 		} else {
8664 			eval_clamshell = true;
8665 		}
8666 	}
8667 
8668 	/*
8669 	 * Overtemp
8670 	 */
8671 	if (msg & kIOPMOverTemp) {
8672 		DLOG("Thermal overtemp message received!\n");
8673 		thermalEmergencyState = true;
8674 		privateSleepSystem(kIOPMSleepReasonThermalEmergency);
8675 	}
8676 
8677 	/*
8678 	 * Forward DW thermal notification to client, if system is not going to sleep
8679 	 */
8680 	if ((msg & kIOPMDWOverTemp) && (_systemTransitionType != kSystemTransitionSleep)) {
8681 		DLOG("DarkWake thermal limits message received!\n");
8682 		messageClients(kIOPMMessageDarkWakeThermalEmergency);
8683 	}
8684 
8685 	/*
8686 	 * Sleep Now!
8687 	 */
8688 	if (msg & kIOPMSleepNow) {
8689 		privateSleepSystem(kIOPMSleepReasonSoftware);
8690 	}
8691 
8692 	/*
8693 	 * Power Emergency
8694 	 */
8695 	if (msg & kIOPMPowerEmergency) {
8696 		DLOG("Received kIOPMPowerEmergency");
8697 #if HIBERNATION && defined(__arm64__)
8698 		if (!ml_is_secure_hib_supported() || ldmHibernateDisable) {
8699 			// Wait for the next low battery notification if the system state is
8700 			// in transition.
8701 			if ((_systemTransitionType == kSystemTransitionNone) &&
8702 			    CAP_CURRENT(kIOPMSystemCapabilityCPU) &&
8703 			    !systemBooting && !systemShutdown && !gWillShutdown) {
8704 				// Setting lowBatteryCondition will prevent system sleep
8705 				lowBatteryCondition = true;
8706 
8707 				// Notify userspace to initiate system shutdown
8708 				DLOG("Initiating userspace shutdown ml_is_secure_hib_supported %d lockdownMode %d", ml_is_secure_hib_supported(), ldmHibernateDisable);
8709 				messageClients(kIOPMMessageRequestSystemShutdown);
8710 			}
8711 		} else {
8712 			lowBatteryCondition = true;
8713 			privateSleepSystem(kIOPMSleepReasonLowPower);
8714 		}
8715 #else  /* HIBERNATION && defined(__arm64__) */
8716 		lowBatteryCondition = true;
8717 		privateSleepSystem(kIOPMSleepReasonLowPower);
8718 #endif /* HIBERNATION && defined(__arm64__) */
8719 	}
8720 
8721 	/*
8722 	 * Clamshell OPEN
8723 	 */
8724 	if (msg & kIOPMClamshellOpened) {
8725 		DLOG("Clamshell opened\n");
8726 		// Received clamshel open message from clamshell controlling driver
8727 		// Update our internal state and tell general interest clients
8728 		clamshellClosed = false;
8729 		clamshellExists = true;
8730 
8731 		// Don't issue a hid tickle when lid is open and polled on wake
8732 		if (msg & kIOPMSetValue) {
8733 			setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
8734 			reportUserInput();
8735 		}
8736 
8737 		// Tell PMCPU
8738 		informCPUStateChange(kInformLid, 0);
8739 
8740 		// Tell general interest clients
8741 		sendClientClamshellNotification();
8742 
8743 		bool aborting =  ((lastSleepReason == kIOPMSleepReasonClamshell)
8744 		    || (lastSleepReason == kIOPMSleepReasonIdle)
8745 		    || (lastSleepReason == kIOPMSleepReasonMaintenance));
8746 		if (aborting) {
8747 			userActivityCount++;
8748 		}
8749 		DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
8750 	}
8751 
8752 	/*
8753 	 * Clamshell CLOSED
8754 	 * Send the clamshell interest notification since the lid is closing.
8755 	 */
8756 	if (msg & kIOPMClamshellClosed) {
8757 		if ((clamshellIgnoreClose || (gClamshellFlags & kClamshell_WAR_38378787)) &&
8758 		    clamshellClosed && clamshellExists) {
8759 			DLOG("Ignoring redundant Clamshell close event\n");
8760 		} else {
8761 			DLOG("Clamshell closed\n");
8762 			// Received clamshel open message from clamshell controlling driver
8763 			// Update our internal state and tell general interest clients
8764 			clamshellClosed = true;
8765 			clamshellExists = true;
8766 
8767 			// Ignore all following clamshell close events until the clamshell
8768 			// is opened or the system sleeps. When a clamshell close triggers
8769 			// a system wake, the lid driver may send us two clamshell close
8770 			// events, one for the clamshell close event itself, and a second
8771 			// close event when the driver polls the lid state on wake.
8772 			clamshellIgnoreClose = true;
8773 
8774 			// Tell PMCPU
8775 			informCPUStateChange(kInformLid, 1);
8776 
8777 			// Tell general interest clients
8778 			sendClientClamshellNotification();
8779 
8780 			// And set eval_clamshell = so we can attempt
8781 			eval_clamshell = true;
8782 		}
8783 	}
8784 
8785 	/*
8786 	 * Set Desktop mode (sent from graphics)
8787 	 *
8788 	 *  -> reevaluate lid state
8789 	 */
8790 	if (msg & kIOPMSetDesktopMode) {
8791 		desktopMode = (0 != (msg & kIOPMSetValue));
8792 		msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
8793 		DLOG("Desktop mode %d\n", desktopMode);
8794 
8795 		sendClientClamshellNotification();
8796 
8797 		// Re-evaluate the lid state
8798 		eval_clamshell = true;
8799 	}
8800 
8801 	/*
8802 	 * AC Adaptor connected
8803 	 *
8804 	 *  -> reevaluate lid state
8805 	 */
8806 	if (msg & kIOPMSetACAdaptorConnected) {
8807 		acAdaptorConnected = (0 != (msg & kIOPMSetValue));
8808 		msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
8809 
8810 		// Tell CPU PM
8811 		informCPUStateChange(kInformAC, !acAdaptorConnected);
8812 
8813 		// Tell BSD if AC is connected
8814 		//      0 == external power source; 1 == on battery
8815 		post_sys_powersource(acAdaptorConnected ? 0:1);
8816 
8817 		sendClientClamshellNotification();
8818 
8819 		IOUserServer::powerSourceChanged(acAdaptorConnected);
8820 
8821 		// Re-evaluate the lid state
8822 		eval_clamshell = true;
8823 
8824 		// Lack of AC may have latched a display wrangler tickle.
8825 		// This mirrors the hardware's USB wake event latch, where a latched
8826 		// USB wake event followed by an AC attach will trigger a full wake.
8827 		latchDisplayWranglerTickle( false );
8828 
8829 #if HIBERNATION
8830 		// AC presence will reset the standy timer delay adjustment.
8831 		_standbyTimerResetSeconds = 0;
8832 #endif
8833 		if (!userIsActive) {
8834 			// Reset userActivityTime when power supply is changed(rdr 13789330)
8835 			clock_get_uptime(&userActivityTime);
8836 		}
8837 	}
8838 
8839 	/*
8840 	 * Enable Clamshell (external display disappear)
8841 	 *
8842 	 *  -> reevaluate lid state
8843 	 */
8844 	if (msg & kIOPMEnableClamshell) {
8845 		DLOG("Clamshell enabled\n");
8846 
8847 		// Re-evaluate the lid state
8848 		// System should sleep on external display disappearance
8849 		// in lid closed operation.
8850 		if (true == clamshellDisabled) {
8851 			eval_clamshell = true;
8852 
8853 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
8854 			// Also clear kClamshellSleepDisableInternal when graphics enables
8855 			// the clamshell during a full wake. When graphics is behaving as
8856 			// expected, this will allow clamshell close to be honored earlier
8857 			// rather than waiting for the delayed evaluation.
8858 			if ((clamshellSleepDisableMask & kClamshellSleepDisableInternal) &&
8859 			    (CAP_PENDING(kIOPMSystemCapabilityGraphics) ||
8860 			    CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
8861 				setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
8862 
8863 				// Cancel the TC to avoid an extra kLocalEvalClamshellCommand
8864 				// when timer expires which is harmless but useless.
8865 				thread_call_cancel(fullWakeThreadCall);
8866 			}
8867 #endif
8868 		}
8869 
8870 		clamshellDisabled = false;
8871 		sendClientClamshellNotification();
8872 	}
8873 
8874 	/*
8875 	 * Disable Clamshell (external display appeared)
8876 	 * We don't bother re-evaluating clamshell state. If the system is awake,
8877 	 * the lid is probably open.
8878 	 */
8879 	if (msg & kIOPMDisableClamshell) {
8880 		DLOG("Clamshell disabled\n");
8881 		clamshellDisabled = true;
8882 		sendClientClamshellNotification();
8883 	}
8884 
8885 	/*
8886 	 * Evaluate clamshell and SLEEP if appropriate
8887 	 */
8888 	if (eval_clamshell_alarm && clamshellClosed) {
8889 		if (shouldSleepOnRTCAlarmWake()) {
8890 			privateSleepSystem(kIOPMSleepReasonClamshell);
8891 		}
8892 	} else if (eval_clamshell && clamshellClosed) {
8893 		if (shouldSleepOnClamshellClosed()) {
8894 			privateSleepSystem(kIOPMSleepReasonClamshell);
8895 		} else {
8896 			evaluatePolicy( kStimulusDarkWakeEvaluate );
8897 		}
8898 	}
8899 
8900 	if (msg & kIOPMProModeEngaged) {
8901 		int newState = 1;
8902 		DLOG("ProModeEngaged\n");
8903 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8904 	}
8905 
8906 	if (msg & kIOPMProModeDisengaged) {
8907 		int newState = 0;
8908 		DLOG("ProModeDisengaged\n");
8909 		messageClient(kIOPMMessageProModeStateChange, systemCapabilityNotifier.get(), &newState, sizeof(newState));
8910 	}
8911 }
8912 
8913 //******************************************************************************
8914 // evaluatePolicy
8915 //
8916 // Evaluate root-domain policy in response to external changes.
8917 //******************************************************************************
8918 
8919 void
8920 IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
8921 {
8922 	union {
8923 		struct {
8924 			int idleSleepEnabled    : 1;
8925 			int idleSleepDisabled   : 1;
8926 			int displaySleep        : 1;
8927 			int sleepDelayChanged   : 1;
8928 			int evaluateDarkWake    : 1;
8929 			int adjustPowerState    : 1;
8930 			int userBecameInactive  : 1;
8931 			int displaySleepEntry   : 1;
8932 		} bit;
8933 		uint32_t u32;
8934 	} flags;
8935 
8936 
8937 	ASSERT_GATED();
8938 	flags.u32 = 0;
8939 
8940 	switch (stimulus) {
8941 	case kStimulusDisplayWranglerSleep:
8942 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8943 		if (!wranglerPowerOff) {
8944 			// wrangler is in sleep state or lower
8945 			flags.bit.displaySleep = true;
8946 		}
8947 		if (!wranglerAsleep) {
8948 			// transition from wrangler wake to wrangler sleep
8949 			flags.bit.displaySleepEntry = true;
8950 			wranglerAsleep = true;
8951 		}
8952 		break;
8953 
8954 	case kStimulusDisplayWranglerWake:
8955 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8956 		displayIdleForDemandSleep = false;
8957 		wranglerPowerOff = false;
8958 		wranglerAsleep = false;
8959 		break;
8960 
8961 	case kStimulusEnterUserActiveState:
8962 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8963 		if (_preventUserActive) {
8964 			DLOG("user active dropped\n");
8965 			break;
8966 		}
8967 		if (!userIsActive) {
8968 			userIsActive = true;
8969 			userWasActive = true;
8970 			clock_get_uptime(&gUserActiveAbsTime);
8971 
8972 			// Stay awake after dropping demand for display power on
8973 			if (kFullWakeReasonDisplayOn == fullWakeReason) {
8974 				fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
8975 				DLOG("User activity while in notification wake\n");
8976 				changePowerStateWithOverrideTo( getRUN_STATE(), 0);
8977 			}
8978 
8979 			kdebugTrace(kPMLogUserActiveState, 0, 1, 0);
8980 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanTrue);
8981 			messageClients(kIOPMMessageUserIsActiveChanged);
8982 		}
8983 		flags.bit.idleSleepDisabled = true;
8984 		break;
8985 
8986 	case kStimulusLeaveUserActiveState:
8987 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
8988 		if (userIsActive) {
8989 			clock_get_uptime(&gUserInactiveAbsTime);
8990 			userIsActive = false;
8991 			clock_get_uptime(&userBecameInactiveTime);
8992 			flags.bit.userBecameInactive = true;
8993 
8994 			kdebugTrace(kPMLogUserActiveState, 0, 0, 0);
8995 			setProperty(gIOPMUserIsActiveKey.get(), kOSBooleanFalse);
8996 			messageClients(kIOPMMessageUserIsActiveChanged);
8997 		}
8998 		break;
8999 
9000 	case kStimulusAggressivenessChanged:
9001 	{
9002 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9003 		unsigned long   aggressiveValue;
9004 		uint32_t        minutesToIdleSleep  = 0;
9005 		uint32_t        minutesToDisplayDim = 0;
9006 		uint32_t        minutesDelta        = 0;
9007 
9008 		// Fetch latest display and system sleep slider values.
9009 		aggressiveValue = 0;
9010 		getAggressiveness(kPMMinutesToSleep, &aggressiveValue);
9011 		minutesToIdleSleep = (uint32_t) aggressiveValue;
9012 
9013 		aggressiveValue = 0;
9014 		getAggressiveness(kPMMinutesToDim, &aggressiveValue);
9015 		minutesToDisplayDim = (uint32_t) aggressiveValue;
9016 		DLOG("aggressiveness changed: system %u->%u, display %u\n",
9017 		    sleepSlider, minutesToIdleSleep, minutesToDisplayDim);
9018 
9019 		DLOG("idle time -> %d ms (ena %d)\n",
9020 		    idleMilliSeconds, (minutesToIdleSleep != 0));
9021 
9022 		// How long to wait before sleeping the system once
9023 		// the displays turns off is indicated by 'extraSleepDelay'.
9024 
9025 		if (minutesToIdleSleep > minutesToDisplayDim) {
9026 			minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
9027 		} else if (minutesToIdleSleep == minutesToDisplayDim) {
9028 			minutesDelta = 1;
9029 		}
9030 
9031 		if ((!idleSleepEnabled) && (minutesToIdleSleep != 0)) {
9032 			idleSleepEnabled = flags.bit.idleSleepEnabled = true;
9033 		}
9034 
9035 		if ((idleSleepEnabled) && (minutesToIdleSleep == 0)) {
9036 			flags.bit.idleSleepDisabled = true;
9037 			idleSleepEnabled = false;
9038 		}
9039 #if !defined(XNU_TARGET_OS_OSX)
9040 		if (0x7fffffff == minutesToIdleSleep) {
9041 			minutesToIdleSleep = idleMilliSeconds / 1000;
9042 		}
9043 #endif /* !defined(XNU_TARGET_OS_OSX) */
9044 
9045 		if (((minutesDelta != extraSleepDelay) ||
9046 		    (userActivityTime != userActivityTime_prev)) &&
9047 		    !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled) {
9048 			flags.bit.sleepDelayChanged = true;
9049 		}
9050 
9051 		if (systemDarkWake && !darkWakeToSleepASAP &&
9052 		    (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled)) {
9053 			// Reconsider decision to remain in dark wake
9054 			flags.bit.evaluateDarkWake = true;
9055 		}
9056 
9057 		sleepSlider = minutesToIdleSleep;
9058 		extraSleepDelay = minutesDelta;
9059 		userActivityTime_prev = userActivityTime;
9060 	}   break;
9061 
9062 	case kStimulusDemandSystemSleep:
9063 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9064 		displayIdleForDemandSleep = true;
9065 		if (wrangler && wranglerIdleSettings) {
9066 			// Request wrangler idle only when demand sleep is triggered
9067 			// from full wake.
9068 			if (CAP_CURRENT(kIOPMSystemCapabilityGraphics)) {
9069 				wrangler->setProperties(wranglerIdleSettings.get());
9070 				DLOG("Requested wrangler idle\n");
9071 			}
9072 		}
9073 		// arg = sleepReason
9074 		changePowerStateWithOverrideTo( SLEEP_STATE, arg );
9075 		break;
9076 
9077 	case kStimulusAllowSystemSleepChanged:
9078 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9079 		flags.bit.adjustPowerState = true;
9080 		break;
9081 
9082 	case kStimulusDarkWakeActivityTickle:
9083 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9084 		// arg == true implies real and not self generated wrangler tickle.
9085 		// Update wake type on PM work loop instead of the tickle thread to
9086 		// eliminate the possibility of an early tickle clobbering the wake
9087 		// type set by the platform driver.
9088 		if (arg == true) {
9089 			setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
9090 		}
9091 
9092 		if (!darkWakeExit) {
9093 			if (latchDisplayWranglerTickle(true)) {
9094 				DLOG("latched tickle\n");
9095 				break;
9096 			}
9097 
9098 			darkWakeExit = true;
9099 			DLOG("Requesting full wake due to dark wake activity tickle\n");
9100 			requestFullWake( kFullWakeReasonLocalUser );
9101 		}
9102 		break;
9103 
9104 	case kStimulusDarkWakeEntry:
9105 	case kStimulusDarkWakeReentry:
9106 		DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9107 		// Any system transitions since the last dark wake transition
9108 		// will invalid the stimulus.
9109 
9110 		if (arg == _systemStateGeneration) {
9111 			DLOG("dark wake entry\n");
9112 			systemDarkWake = true;
9113 
9114 			// Keep wranglerPowerOff an invariant when wrangler is absent
9115 			if (wrangler) {
9116 				wranglerPowerOff = true;
9117 			}
9118 
9119 			if (kStimulusDarkWakeEntry == stimulus) {
9120 				clock_get_uptime(&userBecameInactiveTime);
9121 				flags.bit.evaluateDarkWake = true;
9122 				if (activitySinceSleep()) {
9123 					DLOG("User activity recorded while going to darkwake\n");
9124 					reportUserInput();
9125 				}
9126 			}
9127 
9128 			// Always accelerate disk spindown while in dark wake,
9129 			// even if system does not support/allow sleep.
9130 
9131 			cancelIdleSleepTimer();
9132 			setQuickSpinDownTimeout();
9133 		}
9134 		break;
9135 
9136 	case kStimulusDarkWakeEvaluate:
9137 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9138 		if (systemDarkWake) {
9139 			flags.bit.evaluateDarkWake = true;
9140 		}
9141 		break;
9142 
9143 	case kStimulusNoIdleSleepPreventers:
9144 		DMSG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
9145 		flags.bit.adjustPowerState = true;
9146 		break;
9147 	} /* switch(stimulus) */
9148 
9149 	if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason)) {
9150 		DLOG("DarkWake: sleepASAP %d, clamshell closed %d, disabled %d/%x, desktopMode %d, ac %d\n",
9151 		    darkWakeToSleepASAP, clamshellClosed, clamshellDisabled, clamshellSleepDisableMask, desktopMode, acAdaptorConnected);
9152 		if (darkWakeToSleepASAP ||
9153 		    (clamshellClosed && !(desktopMode && acAdaptorConnected))) {
9154 			uint32_t newSleepReason;
9155 
9156 			if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9157 				// System was previously in full wake. Sleep reason from
9158 				// full to dark already recorded in fullToDarkReason.
9159 
9160 				if (lowBatteryCondition) {
9161 					newSleepReason = kIOPMSleepReasonLowPower;
9162 				} else if (thermalEmergencyState) {
9163 					newSleepReason = kIOPMSleepReasonThermalEmergency;
9164 				} else {
9165 					newSleepReason = fullToDarkReason;
9166 				}
9167 			} else {
9168 				// In dark wake from system sleep.
9169 
9170 				if (darkWakeSleepService) {
9171 					newSleepReason = kIOPMSleepReasonSleepServiceExit;
9172 				} else {
9173 					newSleepReason = kIOPMSleepReasonMaintenance;
9174 				}
9175 			}
9176 
9177 			if (checkSystemCanSleep(newSleepReason)) {
9178 				privateSleepSystem(newSleepReason);
9179 			}
9180 		} else { // non-maintenance (network) dark wake
9181 			if (checkSystemCanSleep(kIOPMSleepReasonIdle)) {
9182 				// Release power clamp, and wait for children idle.
9183 				adjustPowerState(true);
9184 			} else {
9185 				changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonDarkWakeCannotSleep);
9186 			}
9187 		}
9188 	}
9189 
9190 	if (systemDarkWake) {
9191 		// The rest are irrelevant while system is in dark wake.
9192 		flags.u32 = 0;
9193 	}
9194 
9195 	if ((flags.bit.displaySleepEntry) &&
9196 	    (kFullWakeReasonDisplayOn == fullWakeReason)) {
9197 		// kIOPMSleepReasonNotificationWakeExit
9198 		DLOG("Display sleep while in notification wake\n");
9199 		changePowerStateWithOverrideTo(SLEEP_STATE, kIOPMSleepReasonNotificationWakeExit);
9200 	}
9201 
9202 	if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged) {
9203 		bool cancelQuickSpindown = false;
9204 
9205 		if (flags.bit.sleepDelayChanged) {
9206 			// Cancel existing idle sleep timer and quick disk spindown.
9207 			// New settings will be applied by the idleSleepEnabled flag
9208 			// handler below if idle sleep is enabled.
9209 
9210 			DLOG("extra sleep timer changed\n");
9211 			cancelIdleSleepTimer();
9212 			cancelQuickSpindown = true;
9213 		} else {
9214 			DLOG("user inactive\n");
9215 		}
9216 
9217 		if (!userIsActive && idleSleepEnabled) {
9218 			startIdleSleepTimer(getTimeToIdleSleep());
9219 		}
9220 
9221 		if (cancelQuickSpindown) {
9222 			restoreUserSpinDownTimeout();
9223 		}
9224 	}
9225 
9226 	if (flags.bit.idleSleepEnabled) {
9227 		DLOG("idle sleep timer enabled\n");
9228 		if (!wrangler) {
9229 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9230 			startIdleSleepTimer(getTimeToIdleSleep());
9231 #else
9232 			changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonIdleSleepEnabled);
9233 			startIdleSleepTimer( idleMilliSeconds );
9234 #endif
9235 		} else {
9236 			// Start idle timer if prefs now allow system sleep
9237 			// and user is already inactive. Disk spindown is
9238 			// accelerated upon timer expiration.
9239 
9240 			if (!userIsActive) {
9241 				startIdleSleepTimer(getTimeToIdleSleep());
9242 			}
9243 		}
9244 	}
9245 
9246 	if (flags.bit.idleSleepDisabled) {
9247 		DLOG("idle sleep timer disabled\n");
9248 		cancelIdleSleepTimer();
9249 		restoreUserSpinDownTimeout();
9250 		adjustPowerState();
9251 	}
9252 
9253 	if (flags.bit.adjustPowerState) {
9254 		bool sleepASAP = false;
9255 
9256 		if (!systemBooting && (0 == idleSleepPreventersCount())) {
9257 			if (!wrangler) {
9258 				if (kStimulusNoIdleSleepPreventers != stimulus) {
9259 					changePowerStateWithTagToPriv(getRUN_STATE(), kCPSReasonEvaluatePolicy);
9260 				}
9261 				if (idleSleepEnabled) {
9262 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
9263 					if (!extraSleepDelay && !idleSleepTimerPending && !gNoIdleFlag) {
9264 						sleepASAP = true;
9265 					}
9266 #else
9267 					// stay awake for at least idleMilliSeconds
9268 					startIdleSleepTimer(idleMilliSeconds);
9269 #endif
9270 				}
9271 			} else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake && !gNoIdleFlag) {
9272 				sleepASAP = true;
9273 			}
9274 		}
9275 
9276 		adjustPowerState(sleepASAP);
9277 	}
9278 }
9279 
9280 //******************************************************************************
9281 
9282 unsigned int
9283 IOPMrootDomain::idleSleepPreventersCount()
9284 {
9285 	if (_aotMode) {
9286 		unsigned int count __block;
9287 		count = 0;
9288 		preventIdleSleepList->iterateObjects(^bool (OSObject * obj)
9289 		{
9290 			count += (NULL == obj->metaCast("AppleARMBacklight"));
9291 			return false;
9292 		});
9293 		return count;
9294 	}
9295 
9296 	return preventIdleSleepList->getCount();
9297 }
9298 
9299 
9300 //******************************************************************************
9301 // requestFullWake
9302 //
9303 // Request transition from dark wake to full wake
9304 //******************************************************************************
9305 
9306 void
9307 IOPMrootDomain::requestFullWake( FullWakeReason reason )
9308 {
9309 	uint32_t        options = 0;
9310 	IOService *     pciRoot = NULL;
9311 	bool            promotion = false;
9312 
9313 	// System must be in dark wake and a valid reason for entering full wake
9314 	if ((kFullWakeReasonNone == reason) ||
9315 	    (kFullWakeReasonNone != fullWakeReason) ||
9316 	    (CAP_CURRENT(kIOPMSystemCapabilityGraphics))) {
9317 		return;
9318 	}
9319 
9320 	// Will clear reason upon exit from full wake
9321 	fullWakeReason = reason;
9322 
9323 	_desiredCapability |= (kIOPMSystemCapabilityGraphics |
9324 	    kIOPMSystemCapabilityAudio);
9325 
9326 	if ((kSystemTransitionWake == _systemTransitionType) &&
9327 	    !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
9328 	    !darkWakePowerClamped) {
9329 		// Promote to full wake while waking up to dark wake due to tickle.
9330 		// PM will hold off notifying the graphics subsystem about system wake
9331 		// as late as possible, so if a HID tickle does arrive, graphics can
9332 		// power up from this same wake transition. Otherwise, the latency to
9333 		// power up graphics on the following transition can be huge on certain
9334 		// systems. However, once any power clamping has taken effect, it is
9335 		// too late to promote the current dark wake transition to a full wake.
9336 		_pendingCapability |= (kIOPMSystemCapabilityGraphics |
9337 		    kIOPMSystemCapabilityAudio);
9338 
9339 		// Tell the PCI parent of audio and graphics drivers to stop
9340 		// delaying the child notifications. Same for root domain.
9341 		pciRoot = pciHostBridgeDriver.get();
9342 		willEnterFullWake();
9343 		promotion = true;
9344 	}
9345 
9346 	// Unsafe to cancel once graphics was powered.
9347 	// If system woke from dark wake, the return to sleep can
9348 	// be cancelled. "awake -> dark -> sleep" transition
9349 	// can be cancelled also, during the "dark -> sleep" phase
9350 	// *prior* to driver power down.
9351 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
9352 	    _pendingCapability == 0) {
9353 		options |= kIOPMSyncCancelPowerDown;
9354 	}
9355 
9356 	synchronizePowerTree(options, pciRoot);
9357 
9358 	if (kFullWakeReasonLocalUser == fullWakeReason) {
9359 		// IOGraphics doesn't light the display even though graphics is
9360 		// enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
9361 		// So, do an explicit activity tickle
9362 		if (wrangler) {
9363 			wrangler->activityTickle(0, 0);
9364 		}
9365 	}
9366 
9367 	// Log a timestamp for the initial full wake request.
9368 	// System may not always honor this full wake request.
9369 	if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics)) {
9370 		AbsoluteTime    now;
9371 		uint64_t        nsec;
9372 
9373 		clock_get_uptime(&now);
9374 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9375 		absolutetime_to_nanoseconds(now, &nsec);
9376 		MSG("full wake %s (reason %u) %u ms\n",
9377 		    promotion ? "promotion" : "request",
9378 		    fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC)));
9379 	}
9380 }
9381 
9382 //******************************************************************************
9383 // willEnterFullWake
9384 //
9385 // System will enter full wake from sleep, from dark wake, or from dark
9386 // wake promotion. This function aggregate things that are in common to
9387 // all three full wake transitions.
9388 //
9389 // Assumptions: fullWakeReason was updated
9390 //******************************************************************************
9391 
9392 void
9393 IOPMrootDomain::willEnterFullWake( void )
9394 {
9395 	hibernateRetry = false;
9396 	sleepToStandby = false;
9397 	standbyNixed   = false;
9398 	resetTimers    = false;
9399 	sleepTimerMaintenance = false;
9400 
9401 	assert(!CAP_CURRENT(kIOPMSystemCapabilityGraphics));
9402 
9403 	_systemMessageClientMask = kSystemMessageClientPowerd |
9404 	    kSystemMessageClientLegacyApp;
9405 
9406 	if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) {
9407 		// First time to attain full wake capability since the last wake
9408 		_systemMessageClientMask |= kSystemMessageClientKernel;
9409 
9410 		// Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
9411 		setProperty(gIOPMUserTriggeredFullWakeKey.get(),
9412 		    (kFullWakeReasonLocalUser == fullWakeReason) ?
9413 		    kOSBooleanTrue : kOSBooleanFalse);
9414 	}
9415 #if HIBERNATION
9416 	IOHibernateSetWakeCapabilities(_pendingCapability);
9417 #endif
9418 
9419 	IOService::setAdvisoryTickleEnable( true );
9420 	tellClients(kIOMessageSystemWillPowerOn);
9421 	preventTransitionToUserActive(false);
9422 }
9423 
9424 //******************************************************************************
9425 // fullWakeDelayedWork
9426 //
9427 // System has already entered full wake. Invoked by a delayed thread call.
9428 //******************************************************************************
9429 
9430 void
9431 IOPMrootDomain::fullWakeDelayedWork( void )
9432 {
9433 #if DARK_TO_FULL_EVALUATE_CLAMSHELL_DELAY
9434 	if (!gIOPMWorkLoop->inGate()) {
9435 		gIOPMWorkLoop->runAction(
9436 			OSMemberFunctionCast(IOWorkLoop::Action, this,
9437 			&IOPMrootDomain::fullWakeDelayedWork), this);
9438 		return;
9439 	}
9440 
9441 	DLOG("fullWakeDelayedWork cap cur %x pend %x high %x, clamshell disable %x/%x\n",
9442 	    _currentCapability, _pendingCapability, _highestCapability,
9443 	    clamshellDisabled, clamshellSleepDisableMask);
9444 
9445 	if (clamshellExists &&
9446 	    CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
9447 	    !CAP_CHANGE(kIOPMSystemCapabilityGraphics)) {
9448 		if (clamshellSleepDisableMask & kClamshellSleepDisableInternal) {
9449 			setClamShellSleepDisable(false, kClamshellSleepDisableInternal);
9450 		} else {
9451 			// Not the initial full wake after waking from sleep.
9452 			// Evaluate the clamshell for rdar://problem/9157444.
9453 			receivePowerNotification(kLocalEvalClamshellCommand);
9454 		}
9455 	}
9456 #endif
9457 }
9458 
9459 //******************************************************************************
9460 // evaluateAssertions
9461 //
9462 //******************************************************************************
9463 
9464 // Bitmask of all kernel assertions that prevent system idle sleep.
9465 // kIOPMDriverAssertionReservedBit7 is reserved for IOMediaBSDClient.
9466 #define NO_IDLE_SLEEP_ASSERTIONS_MASK \
9467 	(kIOPMDriverAssertionReservedBit7 | \
9468 	 kIOPMDriverAssertionPreventSystemIdleSleepBit)
9469 
9470 void
9471 IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
9472 {
9473 	IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
9474 
9475 	messageClients(kIOPMMessageDriverAssertionsChanged);
9476 
9477 	if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
9478 		if (wrangler) {
9479 			bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
9480 
9481 			DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
9482 			wrangler->setIgnoreIdleTimer( value );
9483 		}
9484 	}
9485 
9486 	if (changedBits & kIOPMDriverAssertionCPUBit) {
9487 		if (_aotNow) {
9488 			IOLog("CPU assertions %d\n", (0 != (kIOPMDriverAssertionCPUBit & newAssertions)));
9489 		}
9490 		evaluatePolicy(_aotNow ? kStimulusNoIdleSleepPreventers : kStimulusDarkWakeEvaluate);
9491 		if (!assertOnWakeSecs && gIOLastWakeAbsTime) {
9492 			AbsoluteTime    now;
9493 			clock_usec_t    microsecs;
9494 			clock_get_uptime(&now);
9495 			SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
9496 			absolutetime_to_microtime(now, &assertOnWakeSecs, &microsecs);
9497 			if (assertOnWakeReport) {
9498 				HISTREPORT_TALLYVALUE(assertOnWakeReport, (int64_t)assertOnWakeSecs);
9499 				DLOG("Updated assertOnWake %lu\n", (unsigned long)assertOnWakeSecs);
9500 			}
9501 		}
9502 	}
9503 
9504 	if (changedBits & NO_IDLE_SLEEP_ASSERTIONS_MASK) {
9505 		if ((newAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) != 0) {
9506 			if ((oldAssertions & NO_IDLE_SLEEP_ASSERTIONS_MASK) == 0) {
9507 				DLOG("PreventIdleSleep driver assertion raised\n");
9508 				bool ok = updatePreventIdleSleepList(this, true);
9509 				if (ok && (changedBits & kIOPMDriverAssertionPreventSystemIdleSleepBit)) {
9510 					// Cancel idle sleep if there is one in progress
9511 					cancelIdlePowerDown(this);
9512 				}
9513 			}
9514 		} else {
9515 			DLOG("PreventIdleSleep driver assertion dropped\n");
9516 			updatePreventIdleSleepList(this, false);
9517 		}
9518 	}
9519 }
9520 
9521 // MARK: -
9522 // MARK: Statistics
9523 
9524 //******************************************************************************
9525 // pmStats
9526 //
9527 //******************************************************************************
9528 
9529 void
9530 IOPMrootDomain::pmStatsRecordEvent(
9531 	int                 eventIndex,
9532 	AbsoluteTime        timestamp)
9533 {
9534 	bool        starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
9535 	bool        stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
9536 	uint64_t    delta;
9537 	uint64_t    nsec;
9538 	OSSharedPtr<OSData> publishPMStats;
9539 
9540 	eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
9541 
9542 	absolutetime_to_nanoseconds(timestamp, &nsec);
9543 
9544 	switch (eventIndex) {
9545 	case kIOPMStatsHibernateImageWrite:
9546 		if (starting) {
9547 			gPMStats.hibWrite.start = nsec;
9548 		} else if (stopping) {
9549 			gPMStats.hibWrite.stop = nsec;
9550 		}
9551 
9552 		if (stopping) {
9553 			delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
9554 			IOLog("PMStats: Hibernate write took %qd ms\n", delta / NSEC_PER_MSEC);
9555 		}
9556 		break;
9557 	case kIOPMStatsHibernateImageRead:
9558 		if (starting) {
9559 			gPMStats.hibRead.start = nsec;
9560 		} else if (stopping) {
9561 			gPMStats.hibRead.stop = nsec;
9562 		}
9563 
9564 		if (stopping) {
9565 			delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
9566 			IOLog("PMStats: Hibernate read took %qd ms\n", delta / NSEC_PER_MSEC);
9567 
9568 			publishPMStats = OSData::withValue(gPMStats);
9569 			setProperty(kIOPMSleepStatisticsKey, publishPMStats.get());
9570 			bzero(&gPMStats, sizeof(gPMStats));
9571 		}
9572 		break;
9573 	}
9574 }
9575 
9576 /*
9577  * Appends a record of the application response to
9578  * IOPMrootDomain::pmStatsAppResponses
9579  */
9580 void
9581 IOPMrootDomain::pmStatsRecordApplicationResponse(
9582 	const OSSymbol      *response,
9583 	const char          *name,
9584 	int                 messageType,
9585 	uint32_t            delay_ms,
9586 	uint64_t            id,
9587 	OSObject            *object,
9588 	IOPMPowerStateIndex powerState,
9589 	bool                async)
9590 {
9591 	OSSharedPtr<OSDictionary>    responseDescription;
9592 	OSSharedPtr<OSNumber>        delayNum;
9593 	OSSharedPtr<OSNumber>        powerCaps;
9594 	OSSharedPtr<OSNumber>        pidNum;
9595 	OSSharedPtr<OSNumber>        msgNum;
9596 	OSSharedPtr<const OSSymbol>  appname;
9597 	OSSharedPtr<const OSSymbol>  sleep;
9598 	OSSharedPtr<const OSSymbol>  wake;
9599 	IOPMServiceInterestNotifier *notify = NULL;
9600 
9601 	if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object))) {
9602 		if (response->isEqualTo(gIOPMStatsResponseTimedOut.get())) {
9603 			notify->ackTimeoutCnt++;
9604 		} else {
9605 			notify->ackTimeoutCnt = 0;
9606 		}
9607 	}
9608 
9609 	if (response->isEqualTo(gIOPMStatsResponsePrompt.get()) ||
9610 	    (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient)) {
9611 		return;
9612 	}
9613 
9614 
9615 	if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9616 		kdebugTrace(kPMLogDrvPSChangeDelay, id, messageType, delay_ms);
9617 	} else if (notify) {
9618 		// User space app or kernel capability client
9619 		if (id) {
9620 			kdebugTrace(kPMLogAppResponseDelay, id, notify->msgType, delay_ms);
9621 		} else {
9622 			kdebugTrace(kPMLogDrvResponseDelay, notify->uuid0, messageType, delay_ms);
9623 		}
9624 		notify->msgType = 0;
9625 	}
9626 
9627 	responseDescription = OSDictionary::withCapacity(5);
9628 	if (responseDescription) {
9629 		if (response) {
9630 			responseDescription->setObject(_statsResponseTypeKey.get(), response);
9631 		}
9632 
9633 		msgNum = OSNumber::withNumber(messageType, 32);
9634 		if (msgNum) {
9635 			responseDescription->setObject(_statsMessageTypeKey.get(), msgNum.get());
9636 		}
9637 
9638 		if (!name && notify && notify->identifier) {
9639 			name = notify->identifier->getCStringNoCopy();
9640 		}
9641 
9642 		if (name && (strlen(name) > 0)) {
9643 			appname = OSSymbol::withCString(name);
9644 			if (appname) {
9645 				responseDescription->setObject(_statsNameKey.get(), appname.get());
9646 			}
9647 		}
9648 
9649 		if (!id && notify) {
9650 			id = notify->uuid0;
9651 		}
9652 		pidNum = OSNumber::withNumber(id, 64);
9653 		if (pidNum) {
9654 			responseDescription->setObject(_statsPIDKey.get(), pidNum.get());
9655 		}
9656 
9657 		delayNum = OSNumber::withNumber(delay_ms, 32);
9658 		if (delayNum) {
9659 			responseDescription->setObject(_statsTimeMSKey.get(), delayNum.get());
9660 		}
9661 
9662 		if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow.get())) {
9663 			powerCaps = OSNumber::withNumber(powerState, 32);
9664 
9665 #if !defined(__i386__) && !defined(__x86_64__) && (DEVELOPMENT || DEBUG)
9666 			static const char * driverCallTypes[] = {
9667 				[kDriverCallInformPreChange]  = "powerStateWillChangeTo",
9668 				[kDriverCallInformPostChange] = "powerStateDidChangeTo",
9669 				[kDriverCallSetPowerState]    = "setPowerState"
9670 			};
9671 
9672 			if (messageType < (sizeof(driverCallTypes) / sizeof(driverCallTypes[0]))) {
9673 				DLOG("%s[0x%qx]::%s(%u) %stook %d ms\n",
9674 				    name, id, driverCallTypes[messageType], (uint32_t) powerState,
9675 				    async ? "async " : "", delay_ms);
9676 			}
9677 #endif
9678 		} else {
9679 			powerCaps = OSNumber::withNumber(_pendingCapability, 32);
9680 		}
9681 		if (powerCaps) {
9682 			responseDescription->setObject(_statsPowerCapsKey.get(), powerCaps.get());
9683 		}
9684 
9685 		sleep = OSSymbol::withCString("Sleep");
9686 		wake = OSSymbol::withCString("Wake");
9687 		if (_systemTransitionType == kSystemTransitionSleep) {
9688 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9689 		} else if (_systemTransitionType == kSystemTransitionWake) {
9690 			responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9691 		} else if (_systemTransitionType == kSystemTransitionCapability) {
9692 			if (CAP_LOSS(kIOPMSystemCapabilityGraphics)) {
9693 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep.get());
9694 			} else if (CAP_GAIN(kIOPMSystemCapabilityGraphics)) {
9695 				responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake.get());
9696 			}
9697 		}
9698 
9699 		IOLockLock(pmStatsLock);
9700 		if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
9701 			pmStatsAppResponses->setObject(responseDescription.get());
9702 		}
9703 		IOLockUnlock(pmStatsLock);
9704 	}
9705 
9706 	return;
9707 }
9708 
9709 // MARK: -
9710 // MARK: PMTraceWorker
9711 
9712 //******************************************************************************
9713 // TracePoint support
9714 //
9715 //******************************************************************************
9716 
9717 #define kIOPMRegisterNVRAMTracePointHandlerKey  \
9718 	"IOPMRegisterNVRAMTracePointHandler"
9719 
9720 IOReturn
9721 IOPMrootDomain::callPlatformFunction(
9722 	const OSSymbol * functionName,
9723 	bool waitForFunction,
9724 	void * param1, void * param2,
9725 	void * param3, void * param4 )
9726 {
9727 	if (pmTracer && functionName &&
9728 	    functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
9729 	    !pmTracer->tracePointHandler && !pmTracer->tracePointTarget) {
9730 		uint32_t    tracePointPhases, tracePointPCI;
9731 		uint64_t    statusCode;
9732 
9733 		pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
9734 		pmTracer->tracePointTarget  = (void *) param2;
9735 		tracePointPCI               = (uint32_t)(uintptr_t) param3;
9736 		tracePointPhases            = (uint32_t)(uintptr_t) param4;
9737 		if ((tracePointPhases & 0xff) == kIOPMTracePointSystemSleep) {
9738 			OSSharedPtr<IORegistryEntry> node = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
9739 			if (node) {
9740 				OSSharedPtr<OSObject> bootRomFailureProp;
9741 				bootRomFailureProp = node->copyProperty(kIOEFIBootRomFailureKey);
9742 				OSData *data = OSDynamicCast(OSData, bootRomFailureProp.get());
9743 				uint32_t bootFailureCode;
9744 				if (data && data->getLength() == sizeof(bootFailureCode)) {
9745 					// Failure code from EFI/BootRom is a four byte structure
9746 					memcpy(&bootFailureCode, data->getBytesNoCopy(), sizeof(bootFailureCode));
9747 					tracePointPCI = OSSwapBigToHostInt32(bootFailureCode);
9748 				}
9749 			}
9750 		}
9751 		statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
9752 		if ((tracePointPhases & 0xff) != kIOPMTracePointSystemUp) {
9753 			MSG("Sleep failure code 0x%08x 0x%08x\n",
9754 			    tracePointPCI, tracePointPhases);
9755 		}
9756 		setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
9757 		pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
9758 
9759 		return kIOReturnSuccess;
9760 	}
9761 #if HIBERNATION
9762 	else if (functionName &&
9763 	    functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey)) {
9764 		if (gSleepPolicyHandler) {
9765 			return kIOReturnExclusiveAccess;
9766 		}
9767 		if (!param1) {
9768 			return kIOReturnBadArgument;
9769 		}
9770 		gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
9771 		gSleepPolicyTarget  = (void *) param2;
9772 		setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
9773 		return kIOReturnSuccess;
9774 	}
9775 #endif
9776 
9777 	return super::callPlatformFunction(
9778 		functionName, waitForFunction, param1, param2, param3, param4);
9779 }
9780 
9781 void
9782 IOPMrootDomain::kdebugTrace(uint32_t event, uint64_t id,
9783     uintptr_t param1, uintptr_t param2, uintptr_t param3)
9784 {
9785 	uint32_t code   = IODBG_POWER(event);
9786 	uint64_t regId  = id;
9787 	if (regId == 0) {
9788 		regId  = getRegistryEntryID();
9789 	}
9790 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, (uintptr_t) regId, param1, param2, param3, 0);
9791 }
9792 
9793 void
9794 IOPMrootDomain::tracePoint( uint8_t point )
9795 {
9796 	if (systemBooting) {
9797 		return;
9798 	}
9799 
9800 	if (kIOPMTracePointWakeCapabilityClients == point) {
9801 		acceptSystemWakeEvents(kAcceptSystemWakeEvents_Disable);
9802 	}
9803 
9804 	kdebugTrace(kPMLogSleepWakeTracePoint, 0, point, 0);
9805 	pmTracer->tracePoint(point);
9806 }
9807 
9808 static void
9809 kext_log_putc(char c)
9810 {
9811 	if (gKextNameEnd || gKextNamePos >= (sizeof(gKextNameBuf) - 1)) {
9812 		return;
9813 	}
9814 	if (c == '(' || c == '[' || c == ' ') {
9815 		c = 0;
9816 		gKextNameEnd = true;
9817 	}
9818 
9819 	gKextNameBuf[gKextNamePos++] = c;
9820 }
9821 
9822 static int
9823 kext_log(const char *fmt, ...)
9824 {
9825 	va_list listp;
9826 
9827 	va_start(listp, fmt);
9828 	_doprnt(fmt, &listp, &kext_log_putc, 16);
9829 	va_end(listp);
9830 
9831 	return 0;
9832 }
9833 
9834 static OSPtr<const OSSymbol>
9835 copyKextIdentifierWithAddress(vm_address_t address)
9836 {
9837 	OSSharedPtr<const OSSymbol> identifer;
9838 
9839 	IOLockLock(gHaltLogLock);
9840 
9841 	gKextNameEnd = false;
9842 	gKextNamePos = 0;
9843 	gKextNameBuf[0] = 0;
9844 
9845 	OSKext::printKextsInBacktrace(&address, 1, kext_log, OSKext::kPrintKextsLock | OSKext::kPrintKextsTerse);
9846 	gKextNameBuf[sizeof(gKextNameBuf) - 1] = 0;
9847 	identifer = OSSymbol::withCString((gKextNameBuf[0] != 0) ? gKextNameBuf : kOSKextKernelIdentifier);
9848 
9849 	IOLockUnlock(gHaltLogLock);
9850 
9851 	return identifer;
9852 }
9853 
9854 // Caller serialized using PM workloop
9855 const char *
9856 IOPMrootDomain::getNotificationClientName(OSObject *object)
9857 {
9858 	IOPMServiceInterestNotifier *notifier = (typeof(notifier))object;
9859 	const char *clientName = "UNKNOWN";
9860 
9861 	if (!notifier->clientName) {
9862 		// Check for user client
9863 		if (systemCapabilityNotifier && (((IOPMServiceInterestNotifier *) systemCapabilityNotifier.get())->handler == notifier->handler)) {
9864 			OSNumber *clientID = NULL;
9865 			messageClient(kIOMessageCopyClientID, object, &clientID);
9866 			if (clientID) {
9867 				OSSharedPtr<OSString> string(IOCopyLogNameForPID(clientID->unsigned32BitValue()), OSNoRetain);
9868 				if (string) {
9869 					notifier->clientName = OSSymbol::withString(string.get());
9870 				}
9871 				clientID->release();
9872 			}
9873 		} else if (notifier->identifier) {
9874 			notifier->clientName.reset(notifier->identifier.get(), OSRetain);
9875 		}
9876 	}
9877 
9878 	if (notifier->clientName) {
9879 		clientName = notifier->clientName->getCStringNoCopy();
9880 	}
9881 
9882 	return clientName;
9883 }
9884 
9885 void
9886 IOPMrootDomain::traceNotification(OSObject *object, bool start, uint64_t timestamp, uint32_t msgIndex)
9887 {
9888 	IOPMServiceInterestNotifier *notifier;
9889 
9890 	if (systemBooting) {
9891 		return;
9892 	}
9893 	notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9894 	if (!notifier) {
9895 		return;
9896 	}
9897 
9898 	if (start) {
9899 		pmTracer->traceDetail(notifier->uuid0 >> 32);
9900 		kdebugTrace(kPMLogSleepWakeMessage, pmTracer->getTracePhase(),
9901 		    (uintptr_t) notifier->msgType, (uintptr_t) notifier->uuid0, (uintptr_t) notifier->uuid1);
9902 
9903 		// Update notifier state used for response/ack logging
9904 		notifier->msgIndex = msgIndex;
9905 		notifier->msgAbsTime = timestamp;
9906 
9907 		if (msgIndex != UINT_MAX) {
9908 			DLOG("%s[%u] to %s\n", getIOMessageString(notifier->msgType), msgIndex, getNotificationClientName(notifier));
9909 		} else {
9910 			DLOG("%s to %s\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9911 		}
9912 
9913 		assert(notifierObject == NULL);
9914 		notifierThread = current_thread();
9915 		notifierObject.reset(notifier, OSRetain);
9916 	} else {
9917 		uint64_t nsec;
9918 		uint32_t delayMS;
9919 
9920 		SUB_ABSOLUTETIME(&timestamp, &notifier->msgAbsTime);
9921 		absolutetime_to_nanoseconds(timestamp, &nsec);
9922 		delayMS = (uint32_t)(nsec / 1000000ULL);
9923 		if (delayMS > notifier->maxMsgDelayMS) {
9924 			notifier->maxMsgDelayMS = delayMS;
9925 		}
9926 
9927 		assert(notifierObject == notifier);
9928 		notifierObject.reset();
9929 		notifierThread = NULL;
9930 	}
9931 }
9932 
9933 void
9934 IOPMrootDomain::traceNotificationAck(OSObject *object, uint32_t delay_ms)
9935 {
9936 	if (systemBooting) {
9937 		return;
9938 	}
9939 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9940 	if (!notifier) {
9941 		return;
9942 	}
9943 
9944 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9945 	    (uintptr_t) notifier->uuid1, (uintptr_t) 0, (uintptr_t) delay_ms);
9946 
9947 	DLOG("%s[%u] ack from %s took %d ms\n",
9948 	    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9949 	if (delay_ms > notifier->maxAckDelayMS) {
9950 		notifier->maxAckDelayMS = delay_ms;
9951 	}
9952 }
9953 
9954 void
9955 IOPMrootDomain::traceNotificationResponse(OSObject *object, uint32_t delay_ms, uint32_t ack_time_us)
9956 {
9957 	if (systemBooting) {
9958 		return;
9959 	}
9960 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9961 	if (!notifier) {
9962 		return;
9963 	}
9964 
9965 	kdebugTrace(kPMLogDrvResponseDelay, notifier->uuid0,
9966 	    (uintptr_t) notifier->uuid1, (uintptr_t)(ack_time_us / 1000), (uintptr_t) delay_ms);
9967 
9968 	if (ack_time_us == 0) {
9969 		// Client work is done and ack will not be forthcoming
9970 		DLOG("%s[%u] response from %s took %d ms\n",
9971 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms);
9972 	} else {
9973 		// Client needs more time and it must ack within ack_time_us
9974 		DLOG("%s[%u] response from %s took %d ms (ack in %d us)\n",
9975 		    getIOMessageString(notifier->msgType), notifier->msgIndex, getNotificationClientName(notifier), delay_ms, ack_time_us);
9976 	}
9977 }
9978 
9979 void
9980 IOPMrootDomain::traceFilteredNotification(OSObject *object)
9981 {
9982 	if ((kIOLogDebugPower & gIOKitDebug) == 0) {
9983 		return;
9984 	}
9985 	if (systemBooting) {
9986 		return;
9987 	}
9988 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, object);
9989 	if (!notifier) {
9990 		return;
9991 	}
9992 
9993 	DLOG("%s to %s dropped\n", getIOMessageString(notifier->msgType), getNotificationClientName(notifier));
9994 }
9995 
9996 void
9997 IOPMrootDomain::traceDetail(uint32_t msgType, uint32_t msgIndex, uint32_t delay)
9998 {
9999 	if (!systemBooting) {
10000 		uint32_t detail = ((msgType & 0xffff) << 16) | (delay & 0xffff);
10001 		pmTracer->traceDetail( detail );
10002 		kdebugTrace(kPMLogSleepWakeTracePoint, pmTracer->getTracePhase(), msgType, delay);
10003 		DLOG("trace point 0x%02x msgType 0x%x detail 0x%08x\n", pmTracer->getTracePhase(), msgType, delay);
10004 	}
10005 }
10006 
10007 void
10008 IOPMrootDomain::configureReportGated(uint64_t channel_id, uint64_t action, void *result)
10009 {
10010 	size_t      reportSize;
10011 	void        **report = NULL;
10012 	uint32_t    bktCnt;
10013 	uint32_t    bktSize;
10014 	uint32_t    *clientCnt;
10015 
10016 	ASSERT_GATED();
10017 
10018 	report = NULL;
10019 	if (channel_id == kAssertDelayChID) {
10020 		report = &assertOnWakeReport;
10021 		bktCnt = kAssertDelayBcktCnt;
10022 		bktSize = kAssertDelayBcktSize;
10023 		clientCnt = &assertOnWakeClientCnt;
10024 	} else if (channel_id == kSleepDelaysChID) {
10025 		report = &sleepDelaysReport;
10026 		bktCnt = kSleepDelaysBcktCnt;
10027 		bktSize = kSleepDelaysBcktSize;
10028 		clientCnt = &sleepDelaysClientCnt;
10029 	} else {
10030 		assert(false);
10031 		return;
10032 	}
10033 
10034 	switch (action) {
10035 	case kIOReportEnable:
10036 
10037 		if (*report) {
10038 			(*clientCnt)++;
10039 			break;
10040 		}
10041 
10042 		reportSize = HISTREPORT_BUFSIZE(bktCnt);
10043 		*report = IOMallocZeroData(reportSize);
10044 		if (*report == NULL) {
10045 			break;
10046 		}
10047 		HISTREPORT_INIT((uint16_t)bktCnt, bktSize, *report, reportSize,
10048 		    getRegistryEntryID(), channel_id, kIOReportCategoryPower);
10049 
10050 		if (channel_id == kAssertDelayChID) {
10051 			assertOnWakeSecs = 0;
10052 		}
10053 
10054 		break;
10055 
10056 	case kIOReportDisable:
10057 		if (*clientCnt == 0) {
10058 			break;
10059 		}
10060 		if (*clientCnt == 1) {
10061 			IOFreeData(*report, HISTREPORT_BUFSIZE(bktCnt));
10062 			*report = NULL;
10063 		}
10064 		(*clientCnt)--;
10065 
10066 		if (channel_id == kAssertDelayChID) {
10067 			assertOnWakeSecs = -1; // Invalid value to prevent updates
10068 		}
10069 		break;
10070 
10071 	case kIOReportGetDimensions:
10072 		if (*report) {
10073 			HISTREPORT_UPDATERES(*report, kIOReportGetDimensions, result);
10074 		}
10075 		break;
10076 	}
10077 
10078 	return;
10079 }
10080 
10081 IOReturn
10082 IOPMrootDomain::configureReport(IOReportChannelList    *channelList,
10083     IOReportConfigureAction action,
10084     void                   *result,
10085     void                   *destination)
10086 {
10087 	unsigned cnt;
10088 	uint64_t configAction = (uint64_t)action;
10089 
10090 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
10091 		if ((channelList->channels[cnt].channel_id == kSleepCntChID) ||
10092 		    (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
10093 		    (channelList->channels[cnt].channel_id == kUserWkCntChID)) {
10094 			if (action != kIOReportGetDimensions) {
10095 				continue;
10096 			}
10097 			SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
10098 		} else if ((channelList->channels[cnt].channel_id == kAssertDelayChID) ||
10099 		    (channelList->channels[cnt].channel_id == kSleepDelaysChID)) {
10100 			gIOPMWorkLoop->runAction(
10101 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::configureReportGated),
10102 				(OSObject *)this, (void *)channelList->channels[cnt].channel_id,
10103 				(void *)configAction, (void *)result);
10104 		}
10105 	}
10106 
10107 	return super::configureReport(channelList, action, result, destination);
10108 }
10109 
10110 IOReturn
10111 IOPMrootDomain::updateReportGated(uint64_t ch_id, void *result, IOBufferMemoryDescriptor *dest)
10112 {
10113 	uint32_t    size2cpy;
10114 	void        *data2cpy;
10115 	void        **report;
10116 
10117 	ASSERT_GATED();
10118 
10119 	report = NULL;
10120 	if (ch_id == kAssertDelayChID) {
10121 		report = &assertOnWakeReport;
10122 	} else if (ch_id == kSleepDelaysChID) {
10123 		report = &sleepDelaysReport;
10124 	} else {
10125 		assert(false);
10126 		return kIOReturnBadArgument;
10127 	}
10128 
10129 	if (*report == NULL) {
10130 		return kIOReturnNotOpen;
10131 	}
10132 
10133 	HISTREPORT_UPDATEPREP(*report, data2cpy, size2cpy);
10134 	if (size2cpy > (dest->getCapacity() - dest->getLength())) {
10135 		return kIOReturnOverrun;
10136 	}
10137 
10138 	HISTREPORT_UPDATERES(*report, kIOReportCopyChannelData, result);
10139 	dest->appendBytes(data2cpy, size2cpy);
10140 
10141 	return kIOReturnSuccess;
10142 }
10143 
10144 IOReturn
10145 IOPMrootDomain::updateReport(IOReportChannelList      *channelList,
10146     IOReportUpdateAction      action,
10147     void                     *result,
10148     void                     *destination)
10149 {
10150 	uint32_t size2cpy;
10151 	void *data2cpy;
10152 	uint8_t buf[SIMPLEREPORT_BUFSIZE];
10153 	IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
10154 	unsigned cnt;
10155 	uint64_t ch_id;
10156 
10157 	if (action != kIOReportCopyChannelData) {
10158 		goto exit;
10159 	}
10160 
10161 	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
10162 		ch_id = channelList->channels[cnt].channel_id;
10163 
10164 		if ((ch_id == kAssertDelayChID) || (ch_id == kSleepDelaysChID)) {
10165 			gIOPMWorkLoop->runAction(
10166 				OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::updateReportGated),
10167 				(OSObject *)this, (void *)ch_id,
10168 				(void *)result, (void *)dest);
10169 			continue;
10170 		} else if ((ch_id == kSleepCntChID) ||
10171 		    (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
10172 			SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
10173 		} else {
10174 			continue;
10175 		}
10176 
10177 		if (ch_id == kSleepCntChID) {
10178 			SIMPLEREPORT_SETVALUE(buf, sleepCnt);
10179 		} else if (ch_id == kDarkWkCntChID) {
10180 			SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
10181 		} else if (ch_id == kUserWkCntChID) {
10182 			SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
10183 		}
10184 
10185 		SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
10186 		SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
10187 		dest->appendBytes(data2cpy, size2cpy);
10188 	}
10189 
10190 exit:
10191 	return super::updateReport(channelList, action, result, destination);
10192 }
10193 
10194 
10195 //******************************************************************************
10196 // PMTraceWorker Class
10197 //
10198 //******************************************************************************
10199 
10200 #undef super
10201 #define super OSObject
10202 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
10203 
10204 #define kPMBestGuessPCIDevicesCount     25
10205 #define kPMMaxRTCBitfieldSize           32
10206 
10207 OSPtr<PMTraceWorker>
10208 PMTraceWorker::tracer(IOPMrootDomain * owner)
10209 {
10210 	OSSharedPtr<PMTraceWorker> me = OSMakeShared<PMTraceWorker>();
10211 	if (!me || !me->init()) {
10212 		return NULL;
10213 	}
10214 
10215 	DLOG("PMTraceWorker %p\n", OBFUSCATE(me.get()));
10216 
10217 	// Note that we cannot instantiate the PCI device -> bit mappings here, since
10218 	// the IODeviceTree has not yet been created by IOPlatformExpert. We create
10219 	// this dictionary lazily.
10220 	me->owner = owner;
10221 	me->pciDeviceBitMappings = NULL;
10222 	me->pmTraceWorkerLock = IOLockAlloc();
10223 	me->tracePhase = kIOPMTracePointSystemUp;
10224 	me->traceData32 = 0;
10225 	me->loginWindowData = 0;
10226 	me->coreDisplayData = 0;
10227 	me->coreGraphicsData = 0;
10228 	return me;
10229 }
10230 
10231 void
10232 PMTraceWorker::RTC_TRACE(void)
10233 {
10234 	if (tracePointHandler && tracePointTarget) {
10235 		uint32_t    wordA;
10236 
10237 		IOLockLock(pmTraceWorkerLock);
10238 		wordA = (loginWindowData << 24) | (coreDisplayData << 16) |
10239 		    (coreGraphicsData << 8) | tracePhase;
10240 		IOLockUnlock(pmTraceWorkerLock);
10241 
10242 		tracePointHandler( tracePointTarget, traceData32, wordA );
10243 		_LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
10244 	}
10245 #if DEVELOPMENT || DEBUG
10246 	if ((swd_panic_phase != 0) && (swd_panic_phase == tracePhase)) {
10247 		DEBUG_LOG("Causing sleep wake failure in phase 0x%08x\n", tracePhase);
10248 		IOLock *l = IOLockAlloc();
10249 		IOLockLock(l);
10250 		IOLockLock(l);
10251 	}
10252 #endif /* DEVELOPMENT || DEBUG */
10253 }
10254 
10255 int
10256 PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
10257 {
10258 	OSSharedPtr<const OSSymbol>    deviceName;
10259 	int                 index = -1;
10260 
10261 	IOLockLock(pmTraceWorkerLock);
10262 
10263 	if (!pciDeviceBitMappings) {
10264 		pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
10265 		if (!pciDeviceBitMappings) {
10266 			goto exit;
10267 		}
10268 	}
10269 
10270 	// Check for bitmask overflow.
10271 	if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize) {
10272 		goto exit;
10273 	}
10274 
10275 	if ((deviceName = pciDevice->copyName()) &&
10276 	    (pciDeviceBitMappings->getNextIndexOfObject(deviceName.get(), 0) == (unsigned int)-1) &&
10277 	    pciDeviceBitMappings->setObject(deviceName.get())) {
10278 		index = pciDeviceBitMappings->getCount() - 1;
10279 		_LOG("PMTrace PCI array: set object %s => %d\n",
10280 		    deviceName->getCStringNoCopy(), index);
10281 	}
10282 
10283 	if (!addedToRegistry && (index >= 0)) {
10284 		addedToRegistry = owner->setProperty("PCITopLevel", this);
10285 	}
10286 
10287 exit:
10288 	IOLockUnlock(pmTraceWorkerLock);
10289 	return index;
10290 }
10291 
10292 bool
10293 PMTraceWorker::serialize(OSSerialize *s) const
10294 {
10295 	bool ok = false;
10296 	if (pciDeviceBitMappings) {
10297 		IOLockLock(pmTraceWorkerLock);
10298 		ok = pciDeviceBitMappings->serialize(s);
10299 		IOLockUnlock(pmTraceWorkerLock);
10300 	}
10301 	return ok;
10302 }
10303 
10304 void
10305 PMTraceWorker::tracePoint(uint8_t phase)
10306 {
10307 	// clear trace detail when phase begins
10308 	if (tracePhase != phase) {
10309 		traceData32 = 0;
10310 	}
10311 
10312 	tracePhase = phase;
10313 
10314 	DLOG("trace point 0x%02x\n", tracePhase);
10315 	RTC_TRACE();
10316 }
10317 
10318 void
10319 PMTraceWorker::traceDetail(uint32_t detail)
10320 {
10321 	if (detail == traceData32) {
10322 		return;
10323 	}
10324 	traceData32 = detail;
10325 	RTC_TRACE();
10326 }
10327 
10328 void
10329 PMTraceWorker::traceComponentWakeProgress(uint32_t component, uint32_t data)
10330 {
10331 	switch (component) {
10332 	case kIOPMLoginWindowProgress:
10333 		loginWindowData = data & kIOPMLoginWindowProgressMask;
10334 		break;
10335 	case kIOPMCoreDisplayProgress:
10336 		coreDisplayData = data & kIOPMCoreDisplayProgressMask;
10337 		break;
10338 	case kIOPMCoreGraphicsProgress:
10339 		coreGraphicsData = data & kIOPMCoreGraphicsProgressMask;
10340 		break;
10341 	default:
10342 		return;
10343 	}
10344 
10345 	DLOG("component trace point 0x%02x data 0x%08x\n", component, data);
10346 	RTC_TRACE();
10347 }
10348 
10349 void
10350 PMTraceWorker::tracePCIPowerChange(
10351 	change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
10352 {
10353 	uint32_t    bitMask;
10354 	uint32_t    expectedFlag;
10355 
10356 	// Ignore PCI changes outside of system sleep/wake.
10357 	if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
10358 	    (kIOPMTracePointWakePowerPlaneDrivers != tracePhase)) {
10359 		return;
10360 	}
10361 
10362 	// Only record the WillChange transition when going to sleep,
10363 	// and the DidChange on the way up.
10364 	changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
10365 	expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
10366 	    kIOPMDomainWillChange : kIOPMDomainDidChange;
10367 	if (changeFlags != expectedFlag) {
10368 		return;
10369 	}
10370 
10371 	// Mark this device off in our bitfield
10372 	if (bitNum < kPMMaxRTCBitfieldSize) {
10373 		bitMask = (1 << bitNum);
10374 
10375 		if (kPowerChangeStart == type) {
10376 			traceData32 |= bitMask;
10377 			_LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n",
10378 			    service->getName(), bitNum, bitMask, traceData32);
10379 			owner->kdebugTrace(kPMLogPCIDevChangeStart, service->getRegistryEntryID(), traceData32, 0);
10380 		} else {
10381 			traceData32 &= ~bitMask;
10382 			_LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
10383 			    service->getName(), bitNum, bitMask, traceData32);
10384 			owner->kdebugTrace(kPMLogPCIDevChangeDone, service->getRegistryEntryID(), traceData32, 0);
10385 		}
10386 
10387 		DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
10388 		RTC_TRACE();
10389 	}
10390 }
10391 
10392 uint64_t
10393 PMTraceWorker::getPMStatusCode()
10394 {
10395 	return ((uint64_t)traceData32 << 32) | ((uint64_t)tracePhase);
10396 }
10397 
10398 uint8_t
10399 PMTraceWorker::getTracePhase()
10400 {
10401 	return tracePhase;
10402 }
10403 
10404 uint32_t
10405 PMTraceWorker::getTraceData()
10406 {
10407 	return traceData32;
10408 }
10409 
10410 // MARK: -
10411 // MARK: PMHaltWorker
10412 
10413 //******************************************************************************
10414 // PMHaltWorker Class
10415 //
10416 //******************************************************************************
10417 
10418 PMHaltWorker *
10419 PMHaltWorker::worker( void )
10420 {
10421 	PMHaltWorker *  me;
10422 	IOThread        thread;
10423 
10424 	do {
10425 		me = OSTypeAlloc( PMHaltWorker );
10426 		if (!me || !me->init()) {
10427 			break;
10428 		}
10429 
10430 		me->lock = IOLockAlloc();
10431 		if (!me->lock) {
10432 			break;
10433 		}
10434 
10435 		DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
10436 		me->retain(); // thread holds extra retain
10437 		if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread)) {
10438 			me->release();
10439 			break;
10440 		}
10441 		thread_deallocate(thread);
10442 		return me;
10443 	} while (false);
10444 
10445 	if (me) {
10446 		me->release();
10447 	}
10448 	return NULL;
10449 }
10450 
10451 void
10452 PMHaltWorker::free( void )
10453 {
10454 	DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
10455 	if (lock) {
10456 		IOLockFree(lock);
10457 		lock = NULL;
10458 	}
10459 	return OSObject::free();
10460 }
10461 
10462 void
10463 PMHaltWorker::main( void * arg, wait_result_t waitResult )
10464 {
10465 	PMHaltWorker * me = (PMHaltWorker *) arg;
10466 
10467 	IOLockLock( gPMHaltLock );
10468 	gPMHaltBusyCount++;
10469 	me->depth = gPMHaltDepth;
10470 	IOLockUnlock( gPMHaltLock );
10471 
10472 	while (me->depth >= 0) {
10473 		PMHaltWorker::work( me );
10474 
10475 		IOLockLock( gPMHaltLock );
10476 		if (++gPMHaltIdleCount >= gPMHaltBusyCount) {
10477 			// This is the last thread to finish work on this level,
10478 			// inform everyone to start working on next lower level.
10479 			gPMHaltDepth--;
10480 			me->depth = gPMHaltDepth;
10481 			gPMHaltIdleCount = 0;
10482 			thread_wakeup((event_t) &gPMHaltIdleCount);
10483 		} else {
10484 			// One or more threads are still working on this level,
10485 			// this thread must wait.
10486 			me->depth = gPMHaltDepth - 1;
10487 			do {
10488 				IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
10489 			} while (me->depth != gPMHaltDepth);
10490 		}
10491 		IOLockUnlock( gPMHaltLock );
10492 	}
10493 
10494 	// No more work to do, terminate thread
10495 	DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
10496 	thread_wakeup( &gPMHaltDepth );
10497 	me->release();
10498 }
10499 
10500 void
10501 PMHaltWorker::work( PMHaltWorker * me )
10502 {
10503 	OSSharedPtr<IOService>     service;
10504 	OSSet *         inner;
10505 	AbsoluteTime    startTime, elapsedTime;
10506 	UInt32          deltaTime;
10507 	bool            timeout;
10508 
10509 	while (true) {
10510 		timeout = false;
10511 
10512 		// Claim an unit of work from the shared pool
10513 		IOLockLock( gPMHaltLock );
10514 		inner = (OSSet *)gPMHaltArray->getObject(me->depth);
10515 		if (inner) {
10516 			service.reset(OSDynamicCast(IOService, inner->getAnyObject()), OSRetain);
10517 			if (service) {
10518 				inner->removeObject(service.get());
10519 			}
10520 		}
10521 		IOLockUnlock( gPMHaltLock );
10522 		if (!service) {
10523 			break; // no more work at this depth
10524 		}
10525 		clock_get_uptime(&startTime);
10526 
10527 		if (!service->isInactive() &&
10528 		    service->setProperty(gPMHaltClientAcknowledgeKey.get(), me)) {
10529 			IOLockLock(me->lock);
10530 			me->startTime = startTime;
10531 			me->service   = service.get();
10532 			me->timeout   = false;
10533 			IOLockUnlock(me->lock);
10534 
10535 			service->systemWillShutdown( gPMHaltMessageType);
10536 
10537 			// Wait for driver acknowledgement
10538 			IOLockLock(me->lock);
10539 			while (service->propertyExists(gPMHaltClientAcknowledgeKey.get())) {
10540 				IOLockSleep(me->lock, me, THREAD_UNINT);
10541 			}
10542 			me->service = NULL;
10543 			timeout = me->timeout;
10544 			IOLockUnlock(me->lock);
10545 		}
10546 
10547 		deltaTime = computeDeltaTimeMS(&startTime, &elapsedTime);
10548 		if ((deltaTime > kPMHaltTimeoutMS) || timeout) {
10549 			LOG("%s driver %s (0x%llx) took %u ms\n",
10550 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?
10551 			    "PowerOff" : "Restart",
10552 			    service->getName(), service->getRegistryEntryID(),
10553 			    (uint32_t) deltaTime );
10554 			halt_log_enter("PowerOff/Restart handler completed",
10555 			    OSMemberFunctionCast(const void *, service.get(), &IOService::systemWillShutdown),
10556 			    elapsedTime);
10557 		}
10558 
10559 		me->visits++;
10560 	}
10561 }
10562 
10563 void
10564 PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
10565 {
10566 	UInt64          nano;
10567 	AbsoluteTime    startTime;
10568 	AbsoluteTime    endTime;
10569 
10570 	endTime = *now;
10571 
10572 	IOLockLock(me->lock);
10573 	if (me->service && !me->timeout) {
10574 		startTime = me->startTime;
10575 		nano = 0;
10576 		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
10577 			SUB_ABSOLUTETIME(&endTime, &startTime);
10578 			absolutetime_to_nanoseconds(endTime, &nano);
10579 		}
10580 		if (nano > 3000000000ULL) {
10581 			me->timeout = true;
10582 
10583 			halt_log_enter("PowerOff/Restart still waiting on handler",
10584 			    OSMemberFunctionCast(const void *, me->service, &IOService::systemWillShutdown),
10585 			    endTime);
10586 			MSG("%s still waiting on %s\n",
10587 			    (gPMHaltMessageType == kIOMessageSystemWillPowerOff) ?  "PowerOff" : "Restart",
10588 			    me->service->getName());
10589 		}
10590 	}
10591 	IOLockUnlock(me->lock);
10592 }
10593 
10594 //******************************************************************************
10595 // acknowledgeSystemWillShutdown
10596 //
10597 // Acknowledgement from drivers that they have prepared for shutdown/restart.
10598 //******************************************************************************
10599 
10600 void
10601 IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
10602 {
10603 	PMHaltWorker            * worker;
10604 	OSSharedPtr<OSObject>     prop;
10605 
10606 	if (!from) {
10607 		return;
10608 	}
10609 
10610 	//DLOG("%s acknowledged\n", from->getName());
10611 	prop = from->copyProperty( gPMHaltClientAcknowledgeKey.get());
10612 	if (prop) {
10613 		worker = (PMHaltWorker *) prop.get();
10614 		IOLockLock(worker->lock);
10615 		from->removeProperty( gPMHaltClientAcknowledgeKey.get());
10616 		thread_wakeup((event_t) worker);
10617 		IOLockUnlock(worker->lock);
10618 	} else {
10619 		DLOG("%s acknowledged without worker property\n",
10620 		    from->getName());
10621 	}
10622 }
10623 
10624 
10625 //******************************************************************************
10626 // notifySystemShutdown
10627 //
10628 // Notify all objects in PM tree that system will shutdown or restart
10629 //******************************************************************************
10630 
10631 static void
10632 notifySystemShutdown( IOService * root, uint32_t messageType )
10633 {
10634 #define PLACEHOLDER ((OSSet *)gPMHaltArray.get())
10635 	OSSharedPtr<IORegistryIterator>  iter;
10636 	IORegistryEntry *                entry;
10637 	IOService *                      node;
10638 	OSSet *                          inner;
10639 	OSSharedPtr<OSSet>               newInner;
10640 	PMHaltWorker *                   workers[kPMHaltMaxWorkers];
10641 	AbsoluteTime                     deadline;
10642 	unsigned int                     totalNodes = 0;
10643 	unsigned int                     depth;
10644 	unsigned int                     rootDepth;
10645 	unsigned int                     numWorkers;
10646 	unsigned int                     count;
10647 	int                              waitResult;
10648 	void *                           baseFunc;
10649 	bool                             ok;
10650 
10651 	DLOG("%s msgType = 0x%x\n", __FUNCTION__, messageType);
10652 
10653 	baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
10654 
10655 	// Iterate the entire PM tree starting from root
10656 
10657 	rootDepth = root->getDepth( gIOPowerPlane );
10658 	if (!rootDepth) {
10659 		goto done;
10660 	}
10661 
10662 	// debug - for repeated test runs
10663 	while (PMHaltWorker::metaClass->getInstanceCount()) {
10664 		IOSleep(1);
10665 	}
10666 
10667 	if (!gPMHaltArray) {
10668 		gPMHaltArray = OSArray::withCapacity(40);
10669 		if (!gPMHaltArray) {
10670 			goto done;
10671 		}
10672 	} else { // debug
10673 		gPMHaltArray->flushCollection();
10674 	}
10675 
10676 	if (!gPMHaltLock) {
10677 		gPMHaltLock = IOLockAlloc();
10678 		if (!gPMHaltLock) {
10679 			goto done;
10680 		}
10681 	}
10682 
10683 	if (!gPMHaltClientAcknowledgeKey) {
10684 		gPMHaltClientAcknowledgeKey =
10685 		    OSSymbol::withCStringNoCopy("PMShutdown");
10686 		if (!gPMHaltClientAcknowledgeKey) {
10687 			goto done;
10688 		}
10689 	}
10690 
10691 	gPMHaltMessageType = messageType;
10692 
10693 	// Depth-first walk of PM plane
10694 
10695 	iter = IORegistryIterator::iterateOver(
10696 		root, gIOPowerPlane, kIORegistryIterateRecursively);
10697 
10698 	if (iter) {
10699 		while ((entry = iter->getNextObject())) {
10700 			node = OSDynamicCast(IOService, entry);
10701 			if (!node) {
10702 				continue;
10703 			}
10704 
10705 			if (baseFunc ==
10706 			    OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown)) {
10707 				continue;
10708 			}
10709 
10710 			depth = node->getDepth( gIOPowerPlane );
10711 			if (depth <= rootDepth) {
10712 				continue;
10713 			}
10714 
10715 			ok = false;
10716 
10717 			// adjust to zero based depth
10718 			depth -= (rootDepth + 1);
10719 
10720 			// gPMHaltArray is an array of containers, each container
10721 			// refers to nodes with the same depth.
10722 
10723 			count = gPMHaltArray->getCount();
10724 			while (depth >= count) {
10725 				// expand array and insert placeholders
10726 				gPMHaltArray->setObject(PLACEHOLDER);
10727 				count++;
10728 			}
10729 			count = gPMHaltArray->getCount();
10730 			if (depth < count) {
10731 				inner = (OSSet *)gPMHaltArray->getObject(depth);
10732 				if (inner == PLACEHOLDER) {
10733 					newInner = OSSet::withCapacity(40);
10734 					if (newInner) {
10735 						gPMHaltArray->replaceObject(depth, newInner.get());
10736 						inner = newInner.get();
10737 					}
10738 				}
10739 
10740 				// PM nodes that appear more than once in the tree will have
10741 				// the same depth, OSSet will refuse to add the node twice.
10742 				if (inner) {
10743 					ok = inner->setObject(node);
10744 				}
10745 			}
10746 			if (!ok) {
10747 				DLOG("Skipped PM node %s\n", node->getName());
10748 			}
10749 		}
10750 	}
10751 
10752 	// debug only
10753 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++) {
10754 		count = 0;
10755 		if (inner != PLACEHOLDER) {
10756 			count = inner->getCount();
10757 		}
10758 		DLOG("Nodes at depth %u = %u\n", i, count);
10759 	}
10760 
10761 	// strip placeholders (not all depths are populated)
10762 	numWorkers = 0;
10763 	for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i));) {
10764 		if (inner == PLACEHOLDER) {
10765 			gPMHaltArray->removeObject(i);
10766 			continue;
10767 		}
10768 		count = inner->getCount();
10769 		if (count > numWorkers) {
10770 			numWorkers = count;
10771 		}
10772 		totalNodes += count;
10773 		i++;
10774 	}
10775 
10776 	if (gPMHaltArray->getCount() == 0 || !numWorkers) {
10777 		goto done;
10778 	}
10779 
10780 	gPMHaltBusyCount = 0;
10781 	gPMHaltIdleCount = 0;
10782 	gPMHaltDepth = gPMHaltArray->getCount() - 1;
10783 
10784 	// Create multiple workers (and threads)
10785 
10786 	if (numWorkers > kPMHaltMaxWorkers) {
10787 		numWorkers = kPMHaltMaxWorkers;
10788 	}
10789 
10790 	DLOG("PM nodes %u, maxDepth %u, workers %u\n",
10791 	    totalNodes, gPMHaltArray->getCount(), numWorkers);
10792 
10793 	for (unsigned int i = 0; i < numWorkers; i++) {
10794 		workers[i] = PMHaltWorker::worker();
10795 	}
10796 
10797 	// Wait for workers to exhaust all available work
10798 
10799 	IOLockLock(gPMHaltLock);
10800 	while (gPMHaltDepth >= 0) {
10801 		clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
10802 
10803 		waitResult = IOLockSleepDeadline(
10804 			gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
10805 		if (THREAD_TIMED_OUT == waitResult) {
10806 			AbsoluteTime now;
10807 			clock_get_uptime(&now);
10808 
10809 			IOLockUnlock(gPMHaltLock);
10810 			for (unsigned int i = 0; i < numWorkers; i++) {
10811 				if (workers[i]) {
10812 					PMHaltWorker::checkTimeout(workers[i], &now);
10813 				}
10814 			}
10815 			IOLockLock(gPMHaltLock);
10816 		}
10817 	}
10818 	IOLockUnlock(gPMHaltLock);
10819 
10820 	// Release all workers
10821 
10822 	for (unsigned int i = 0; i < numWorkers; i++) {
10823 		if (workers[i]) {
10824 			workers[i]->release();
10825 		}
10826 		// worker also retained by it's own thread
10827 	}
10828 
10829 done:
10830 	DLOG("%s done\n", __FUNCTION__);
10831 	return;
10832 }
10833 
10834 // MARK: -
10835 // MARK: Kernel Assertion
10836 
10837 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10838 
10839 IOPMDriverAssertionID
10840 IOPMrootDomain::createPMAssertion(
10841 	IOPMDriverAssertionType whichAssertionBits,
10842 	IOPMDriverAssertionLevel assertionLevel,
10843 	IOService *ownerService,
10844 	const char *ownerDescription)
10845 {
10846 	IOReturn            ret;
10847 	IOPMDriverAssertionID     newAssertion;
10848 
10849 	if (!pmAssertions) {
10850 		return 0;
10851 	}
10852 
10853 	ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
10854 
10855 	if (kIOReturnSuccess == ret) {
10856 #if (DEVELOPMENT || DEBUG)
10857 		if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10858 			const char *serviceName = (ownerService && ownerService->reserved) ? ownerService->getName() : NULL;
10859 			OSReportWithBacktrace("PMRD: createPMAssertion(0x%qx) %s (%s)", newAssertion,
10860 			    serviceName, ownerDescription);
10861 		}
10862 #endif /* (DEVELOPMENT || DEBUG) */
10863 
10864 		const bool waitForWakeup = (whichAssertionBits & kIOPMDriverAssertionForceWakeupBit);
10865 		if (waitForWakeup) {
10866 			waitForSystemTransitionToMinPowerState(AOT_STATE);
10867 		}
10868 
10869 		return newAssertion;
10870 	} else {
10871 		return 0;
10872 	}
10873 }
10874 
10875 IOReturn
10876 IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
10877 {
10878 #if (DEVELOPMENT || DEBUG)
10879 	if (_aotNow || (kIOLogPMRootDomain & gIOKitDebug)) {
10880 		PMAssertStruct *details = pmAssertions->detailsForID(releaseAssertion, NULL);
10881 		if (details) {
10882 			const char *serviceName = (details->ownerService && details->ownerService->reserved) ?
10883 			    details->ownerService->getName() : NULL;
10884 			const char *ownerString = details->ownerString ? details->ownerString->getCStringNoCopy() : NULL;
10885 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx) %s (%s)", releaseAssertion, serviceName, ownerString);
10886 		} else {
10887 			OSReportWithBacktrace("PMRD: releasePMAssertion(0x%qx)", releaseAssertion);
10888 		}
10889 	}
10890 #endif /* (DEVELOPMENT || DEBUG) */
10891 	if (!pmAssertions) {
10892 		return kIOReturnInternalError;
10893 	}
10894 	return pmAssertions->releaseAssertion(releaseAssertion);
10895 }
10896 
10897 
10898 IOReturn
10899 IOPMrootDomain::setPMAssertionLevel(
10900 	IOPMDriverAssertionID assertionID,
10901 	IOPMDriverAssertionLevel assertionLevel)
10902 {
10903 	return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
10904 }
10905 
10906 IOPMDriverAssertionLevel
10907 IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
10908 {
10909 	IOPMDriverAssertionType       sysLevels;
10910 
10911 	if (!pmAssertions || whichAssertion == 0) {
10912 		return kIOPMDriverAssertionLevelOff;
10913 	}
10914 
10915 	sysLevels = pmAssertions->getActivatedAssertions();
10916 
10917 	// Check that every bit set in argument 'whichAssertion' is asserted
10918 	// in the aggregate bits.
10919 	if ((sysLevels & whichAssertion) == whichAssertion) {
10920 		return kIOPMDriverAssertionLevelOn;
10921 	} else {
10922 		return kIOPMDriverAssertionLevelOff;
10923 	}
10924 }
10925 
10926 IOReturn
10927 IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
10928 {
10929 	if (!pmAssertions) {
10930 		return kIOReturnNotFound;
10931 	}
10932 
10933 	return pmAssertions->setUserAssertionLevels(inLevels);
10934 }
10935 
10936 IOReturn
10937 IOPMrootDomain::acquireDriverKitMatchingAssertion()
10938 {
10939 	return gIOPMWorkLoop->runActionBlock(^{
10940 		if (_driverKitMatchingAssertionCount != 0) {
10941 		        _driverKitMatchingAssertionCount++;
10942 		        return kIOReturnSuccess;
10943 		} else {
10944 		        if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10945 		                // system going to sleep
10946 		                return kIOReturnBusy;
10947 			} else {
10948 		                // createPMAssertion is asynchronous.
10949 		                // we must also set _driverKitMatchingAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10950 		                // The assertion is used so that on release, we reevaluate all assertions
10951 		                _driverKitMatchingAssertion = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, "DK matching");
10952 		                if (_driverKitMatchingAssertion != kIOPMUndefinedDriverAssertionID) {
10953 		                        _driverKitMatchingAssertionCount = 1;
10954 		                        return kIOReturnSuccess;
10955 				} else {
10956 		                        return kIOReturnBusy;
10957 				}
10958 			}
10959 		}
10960 	});
10961 }
10962 
10963 void
10964 IOPMrootDomain::releaseDriverKitMatchingAssertion()
10965 {
10966 	gIOPMWorkLoop->runActionBlock(^{
10967 		if (_driverKitMatchingAssertionCount != 0) {
10968 		        _driverKitMatchingAssertionCount--;
10969 		        if (_driverKitMatchingAssertionCount == 0) {
10970 		                releasePMAssertion(_driverKitMatchingAssertion);
10971 		                _driverKitMatchingAssertion = kIOPMUndefinedDriverAssertionID;
10972 			}
10973 		} else {
10974 		        panic("Over-release of driverkit matching assertion");
10975 		}
10976 		return kIOReturnSuccess;
10977 	});
10978 }
10979 
10980 IOReturn
10981 IOPMrootDomain::acquireDriverKitSyncedAssertion(IOService * from, IOPMDriverAssertionID * assertionID)
10982 {
10983 	return gIOPMWorkLoop->runActionBlock(^{
10984 		if (kSystemTransitionSleep == _systemTransitionType && !idleSleepRevertible) {
10985 		        // system going to sleep
10986 		        return kIOReturnBusy;
10987 		}
10988 		// createPMAssertion is asynchronous.
10989 		// we must also set _driverKitSyncedAssertionCount under the PM workloop lock so that we can cancel sleep immediately
10990 		// only kIOPMDriverAssertionCPUBit is used for "synced" assertion
10991 		*assertionID = createPMAssertion(kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, this, from->getName());
10992 		if (*assertionID != kIOPMUndefinedDriverAssertionID) {
10993 		        _driverKitSyncedAssertionCount++;
10994 		        return kIOReturnSuccess;
10995 		} else {
10996 		        return kIOReturnBusy;
10997 		}
10998 	});
10999 }
11000 
11001 void
11002 IOPMrootDomain::releaseDriverKitSyncedAssertion(IOPMDriverAssertionID assertionID)
11003 {
11004 	gIOPMWorkLoop->runActionBlock(^{
11005 		if (_driverKitSyncedAssertionCount != 0) {
11006 		        _driverKitSyncedAssertionCount--;
11007 		        releasePMAssertion(assertionID);
11008 		} else {
11009 		        panic("Over-release of driverkit synced assertion");
11010 		}
11011 		return kIOReturnSuccess;
11012 	});
11013 }
11014 
11015 
11016 IOReturn
11017 IOPMrootDomain::createPMAssertionSafe(
11018 	IOPMDriverAssertionID *assertionID,
11019 	IOPMDriverAssertionType whichAssertionBits,
11020 	IOPMDriverAssertionLevel assertionLevel,
11021 	IOService *ownerService,
11022 	const char *ownerDescription)
11023 {
11024 	IOReturn ret;
11025 	IOPMDriverAssertionID __block id;
11026 
11027 	if (!assertionID) {
11028 		return kIOReturnBadArgument;
11029 	}
11030 
11031 	// Grab workloop to check current transition
11032 	ret = gIOPMWorkLoop->runActionBlock(^{
11033 		if (_systemTransitionType == kSystemTransitionSleep) {
11034 		        return kIOReturnBusy;
11035 		}
11036 		id = createPMAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription);
11037 		return id ? kIOReturnSuccess : kIOReturnError;
11038 	});
11039 
11040 	if (ret == kIOReturnSuccess) {
11041 		*assertionID = id;
11042 	} else if (ret == kIOReturnBusy && (kIOLogPMRootDomain & gIOKitDebug)) {
11043 		DLOG("assertion denied due to ongoing sleep transition (%s)\n", ownerDescription);
11044 	}
11045 
11046 	return ret;
11047 }
11048 
11049 bool
11050 IOPMrootDomain::serializeProperties( OSSerialize * s ) const
11051 {
11052 	if (pmAssertions) {
11053 		pmAssertions->publishProperties();
11054 	}
11055 	return IOService::serializeProperties(s);
11056 }
11057 
11058 OSSharedPtr<OSObject>
11059 IOPMrootDomain::copyProperty( const char * aKey) const
11060 {
11061 	OSSharedPtr<OSObject> obj;
11062 	obj = IOService::copyProperty(aKey);
11063 
11064 	if (obj) {
11065 		return obj;
11066 	}
11067 
11068 	if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
11069 	    sizeof(kIOPMSleepWakeWdogRebootKey))) {
11070 		if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
11071 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11072 		} else {
11073 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11074 		}
11075 	}
11076 
11077 	if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
11078 	    sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
11079 		if (swd_flags & SWD_VALID_LOGS) {
11080 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11081 		} else {
11082 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11083 		}
11084 	}
11085 
11086 	/*
11087 	 * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey'
11088 	 * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
11089 	 * issued by DisplayWrangler on darkwake.
11090 	 */
11091 	if (!strcmp(aKey, "DesktopMode")) {
11092 		if (desktopMode) {
11093 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11094 		} else {
11095 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11096 		}
11097 	}
11098 	if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
11099 		if (displayIdleForDemandSleep) {
11100 			return OSSharedPtr<OSBoolean>(kOSBooleanTrue, OSNoRetain);
11101 		} else {
11102 			return OSSharedPtr<OSBoolean>(kOSBooleanFalse, OSNoRetain);
11103 		}
11104 	}
11105 
11106 	if (!strcmp(aKey, kIOPMDriverWakeEventsKey)) {
11107 		OSSharedPtr<OSArray> array;
11108 		WAKEEVENT_LOCK();
11109 		if (_systemWakeEventsArray && _systemWakeEventsArray->getCount()) {
11110 			OSSharedPtr<OSCollection> collection = _systemWakeEventsArray->copyCollection();
11111 			if (collection) {
11112 				array = OSDynamicPtrCast<OSArray>(collection);
11113 			}
11114 		}
11115 		WAKEEVENT_UNLOCK();
11116 		return os::move(array);
11117 	}
11118 
11119 	if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey)) {
11120 		OSSharedPtr<OSArray> array;
11121 		IOLockLock(pmStatsLock);
11122 		if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
11123 			OSSharedPtr<OSCollection> collection = pmStatsAppResponses->copyCollection();
11124 			if (collection) {
11125 				array = OSDynamicPtrCast<OSArray>(collection);
11126 			}
11127 		}
11128 		IOLockUnlock(pmStatsLock);
11129 		return os::move(array);
11130 	}
11131 
11132 	if (!strcmp(aKey, kIOPMIdleSleepPreventersKey)) {
11133 		OSArray *idleSleepList = NULL;
11134 		gRootDomain->copySleepPreventersList(&idleSleepList, NULL);
11135 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
11136 	}
11137 
11138 	if (!strcmp(aKey, kIOPMSystemSleepPreventersKey)) {
11139 		OSArray *systemSleepList = NULL;
11140 		gRootDomain->copySleepPreventersList(NULL, &systemSleepList);
11141 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
11142 	}
11143 
11144 	if (!strcmp(aKey, kIOPMIdleSleepPreventersWithIDKey)) {
11145 		OSArray *idleSleepList = NULL;
11146 		gRootDomain->copySleepPreventersListWithID(&idleSleepList, NULL);
11147 		return OSSharedPtr<OSArray>(idleSleepList, OSNoRetain);
11148 	}
11149 
11150 	if (!strcmp(aKey, kIOPMSystemSleepPreventersWithIDKey)) {
11151 		OSArray *systemSleepList = NULL;
11152 		gRootDomain->copySleepPreventersListWithID(NULL, &systemSleepList);
11153 		return OSSharedPtr<OSArray>(systemSleepList, OSNoRetain);
11154 	}
11155 	return NULL;
11156 }
11157 
11158 // MARK: -
11159 // MARK: Wake Event Reporting
11160 
11161 void
11162 IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
11163 {
11164 	WAKEEVENT_LOCK();
11165 	strlcpy(outBuf, gWakeReasonString, bufSize);
11166 	WAKEEVENT_UNLOCK();
11167 }
11168 
11169 void
11170 IOPMrootDomain::copyShutdownReasonString( char * outBuf, size_t bufSize )
11171 {
11172 	WAKEEVENT_LOCK();
11173 	strlcpy(outBuf, gShutdownReasonString, bufSize);
11174 	WAKEEVENT_UNLOCK();
11175 }
11176 
11177 void
11178 IOPMrootDomain::copyShutdownTime( uint64_t * time )
11179 {
11180 	WAKEEVENT_LOCK();
11181 	*time = gShutdownTime;
11182 	WAKEEVENT_UNLOCK();
11183 }
11184 
11185 //******************************************************************************
11186 // acceptSystemWakeEvents
11187 //
11188 // Private control for the acceptance of driver wake event claims.
11189 //******************************************************************************
11190 
11191 void
11192 IOPMrootDomain::acceptSystemWakeEvents( uint32_t control )
11193 {
11194 	bool logWakeReason = false;
11195 
11196 	WAKEEVENT_LOCK();
11197 	switch (control) {
11198 	case kAcceptSystemWakeEvents_Enable:
11199 		assert(_acceptSystemWakeEvents == false);
11200 		if (!_systemWakeEventsArray) {
11201 			_systemWakeEventsArray = OSArray::withCapacity(4);
11202 		}
11203 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
11204 		if (!(_aotNow && (kIOPMWakeEventAOTExitFlags & _aotPendingFlags))) {
11205 			gWakeReasonString[0] = '\0';
11206 			if (_systemWakeEventsArray) {
11207 				_systemWakeEventsArray->flushCollection();
11208 			}
11209 		}
11210 
11211 		// Remove stale WakeType property before system sleep
11212 		removeProperty(kIOPMRootDomainWakeTypeKey);
11213 		removeProperty(kIOPMRootDomainWakeReasonKey);
11214 		break;
11215 
11216 	case kAcceptSystemWakeEvents_Disable:
11217 		_acceptSystemWakeEvents = false;
11218 #if defined(XNU_TARGET_OS_OSX)
11219 		logWakeReason = (gWakeReasonString[0] != '\0');
11220 #else /* !defined(XNU_TARGET_OS_OSX) */
11221 		logWakeReason = gWakeReasonSysctlRegistered;
11222 #if DEVELOPMENT
11223 		static int panic_allowed = -1;
11224 
11225 		if ((panic_allowed == -1) &&
11226 		    (PE_parse_boot_argn("swd_wakereason_panic", &panic_allowed, sizeof(panic_allowed)) == false)) {
11227 			panic_allowed = 0;
11228 		}
11229 
11230 		if (panic_allowed) {
11231 			size_t i = 0;
11232 			// Panic if wake reason is null or empty
11233 			for (i = 0; (i < strlen(gWakeReasonString)); i++) {
11234 				if ((gWakeReasonString[i] != ' ') && (gWakeReasonString[i] != '\t')) {
11235 					break;
11236 				}
11237 			}
11238 			if (i >= strlen(gWakeReasonString)) {
11239 				panic("Wake reason is empty");
11240 			}
11241 		}
11242 #endif /* DEVELOPMENT */
11243 #endif /* !defined(XNU_TARGET_OS_OSX) */
11244 
11245 		// publish kIOPMRootDomainWakeReasonKey if not already set
11246 		if (!propertyExists(kIOPMRootDomainWakeReasonKey)) {
11247 			setProperty(kIOPMRootDomainWakeReasonKey, gWakeReasonString);
11248 		}
11249 		break;
11250 
11251 	case kAcceptSystemWakeEvents_Reenable:
11252 		assert(_acceptSystemWakeEvents == false);
11253 		_acceptSystemWakeEvents = (_systemWakeEventsArray != NULL);
11254 		removeProperty(kIOPMRootDomainWakeReasonKey);
11255 		break;
11256 	}
11257 	WAKEEVENT_UNLOCK();
11258 
11259 	if (logWakeReason) {
11260 		MSG("system wake events: %s\n", gWakeReasonString);
11261 	}
11262 }
11263 
11264 //******************************************************************************
11265 // claimSystemWakeEvent
11266 //
11267 // For a driver to claim a device is the source/conduit of a system wake event.
11268 //******************************************************************************
11269 
11270 void
11271 IOPMrootDomain::claimSystemWakeEvent(
11272 	IOService *     device,
11273 	IOOptionBits    flags,
11274 	const char *    reason,
11275 	OSObject *      details )
11276 {
11277 	OSSharedPtr<const OSSymbol>     deviceName;
11278 	OSSharedPtr<OSNumber>           deviceRegId;
11279 	OSSharedPtr<OSNumber>           claimTime;
11280 	OSSharedPtr<OSData>             flagsData;
11281 	OSSharedPtr<OSString>           reasonString;
11282 	OSSharedPtr<OSDictionary>       dict;
11283 	uint64_t                        timestamp;
11284 	bool                            addWakeReason;
11285 
11286 	if (!device || !reason) {
11287 		return;
11288 	}
11289 
11290 	pmEventTimeStamp(&timestamp);
11291 
11292 	uint64_t args[3] = {};
11293 	strlcpy((char *)args, reason, sizeof(args));
11294 	kdebugTrace(kPMLogClaimSystemWake, args[0], args[1], args[2], device->getRegistryEntryID());
11295 
11296 	IOOptionBits        aotFlags = 0;
11297 	bool                needAOTEvaluate = FALSE;
11298 
11299 	if ((kIOPMAOTModeAddEventFlags & _aotMode) && (!flags || (flags == kIOPMWakeEventSource))) {
11300 		flags |= kIOPMWakeEventAOTExit;
11301 
11302 		// Only allow lingering in AOT_STATE for the two wake reasons used for the wrist raise gesture.
11303 		if (!strcmp("AOP.OutboxNotEmpty", reason) || !strcmp("spu_gesture", reason)) {
11304 			flags &= ~kIOPMWakeEventAOTExit;
11305 		}
11306 	}
11307 
11308 #if defined(XNU_TARGET_OS_OSX) && !DISPLAY_WRANGLER_PRESENT
11309 	// Publishing the WakeType is serialized by the PM work loop
11310 	if (!strcmp("rtc", reason) && (_nextScheduledAlarmType != NULL)) {
11311 		pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11312 		    (void *) _nextScheduledAlarmType.get());
11313 	}
11314 
11315 	// Workaround for the missing wake HID event
11316 	if (gDarkWakeFlags & kDarkWakeFlagUserWakeWorkaround) {
11317 		if (!strcmp("trackpadkeyboard", reason)) {
11318 			pmPowerStateQueue->submitPowerEvent(kPowerEventPublishWakeType,
11319 			    (void *) gIOPMWakeTypeUserKey.get());
11320 		}
11321 	}
11322 #endif
11323 
11324 	deviceName   = device->copyName(gIOServicePlane);
11325 	deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
11326 	claimTime    = OSNumber::withNumber(timestamp, 64);
11327 	flagsData    = OSData::withValue(flags);
11328 	reasonString = OSString::withCString(reason);
11329 	dict = OSDictionary::withCapacity(5 + (details ? 1 : 0));
11330 	if (!dict || !deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString) {
11331 		goto done;
11332 	}
11333 
11334 	dict->setObject(gIONameKey, deviceName.get());
11335 	dict->setObject(gIORegistryEntryIDKey, deviceRegId.get());
11336 	dict->setObject(kIOPMWakeEventTimeKey, claimTime.get());
11337 	dict->setObject(kIOPMWakeEventFlagsKey, flagsData.get());
11338 	dict->setObject(kIOPMWakeEventReasonKey, reasonString.get());
11339 	if (details) {
11340 		dict->setObject(kIOPMWakeEventDetailsKey, details);
11341 	}
11342 
11343 	WAKEEVENT_LOCK();
11344 	addWakeReason = _acceptSystemWakeEvents;
11345 	if (_aotMode) {
11346 		IOLog("claimSystemWakeEvent(%s, %s, 0x%x) 0x%x %d\n", reason, deviceName->getCStringNoCopy(), (int)flags, _aotPendingFlags, _aotReadyToFullWake);
11347 	}
11348 	aotFlags        = (kIOPMWakeEventAOTFlags & flags);
11349 	aotFlags        = (aotFlags & ~_aotPendingFlags);
11350 	needAOTEvaluate = false;
11351 	if (_aotNow && aotFlags) {
11352 		if (kIOPMWakeEventAOTPossibleExit & flags) {
11353 			_aotMetrics->possibleCount++;
11354 		}
11355 		if (kIOPMWakeEventAOTConfirmedPossibleExit & flags) {
11356 			_aotMetrics->confirmedPossibleCount++;
11357 		}
11358 		if (kIOPMWakeEventAOTRejectedPossibleExit & flags) {
11359 			_aotMetrics->rejectedPossibleCount++;
11360 		}
11361 		if (kIOPMWakeEventAOTExpiredPossibleExit & flags) {
11362 			_aotMetrics->expiredPossibleCount++;
11363 		}
11364 
11365 		_aotPendingFlags |= aotFlags;
11366 		addWakeReason     = _aotNow && _systemWakeEventsArray && ((kIOPMWakeEventAOTExitFlags & aotFlags));
11367 		needAOTEvaluate   = _aotReadyToFullWake;
11368 	}
11369 	DMSG("claimSystemWakeEvent(%s, 0x%x, %s, 0x%llx) aot %d phase 0x%x add %d\n",
11370 	    reason, (int)flags, deviceName->getCStringNoCopy(), device->getRegistryEntryID(),
11371 	    _aotNow, pmTracer->getTracePhase(), addWakeReason);
11372 
11373 #if DEVELOPMENT || DEBUG
11374 	if (addWakeReason) {
11375 		record_system_event(SYSTEM_EVENT_TYPE_INFO,
11376 		    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11377 		    "Report System Wake Event",
11378 		    "Reason: %s Flags: 0x%x Device: %s, DeviceRegEntry: 0x%llx\n",
11379 		    reason,
11380 		    (int)flags,
11381 		    deviceName->getCStringNoCopy(),
11382 		    device->getRegistryEntryID()
11383 		    );
11384 	}
11385 #endif /* DEVELOPMENT || DEBUG */
11386 
11387 	if (!gWakeReasonSysctlRegistered) {
11388 		// Lazy registration until the platform driver stops registering
11389 		// the same name.
11390 		gWakeReasonSysctlRegistered = true;
11391 	}
11392 	if (addWakeReason) {
11393 		_systemWakeEventsArray->setObject(dict.get());
11394 		if (gWakeReasonString[0] != '\0') {
11395 			strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
11396 		}
11397 		strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
11398 	}
11399 
11400 	WAKEEVENT_UNLOCK();
11401 	if (needAOTEvaluate) {
11402 		// Call aotEvaluate() on PM work loop since it may call
11403 		// aotExit() which accesses PM state.
11404 		pmPowerStateQueue->submitPowerEvent(kPowerEventAOTEvaluate);
11405 	}
11406 
11407 done:
11408 	return;
11409 }
11410 
11411 //******************************************************************************
11412 // claimSystemBootEvent
11413 //
11414 // For a driver to claim a device is the source/conduit of a system boot event.
11415 //******************************************************************************
11416 
11417 void
11418 IOPMrootDomain::claimSystemBootEvent(
11419 	IOService *              device,
11420 	IOOptionBits             flags,
11421 	const char *             reason,
11422 	__unused OSObject *      details )
11423 {
11424 	if (!device || !reason) {
11425 		return;
11426 	}
11427 
11428 	DEBUG_LOG("claimSystemBootEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11429 #if DEVELOPMENT || DEBUG
11430 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11431 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11432 	    "Report System Boot Device",
11433 	    "Reason: %s Flags: 0x%x Device: %s",
11434 	    reason,
11435 	    (int)flags,
11436 	    device->getName()
11437 	    );
11438 #endif /* DEVELOPMENT || DEBUG */
11439 	WAKEEVENT_LOCK();
11440 	if (!gBootReasonSysctlRegistered) {
11441 		// Lazy sysctl registration after setting gBootReasonString
11442 		strlcat(gBootReasonString, reason, sizeof(gBootReasonString));
11443 		os_atomic_store(&gBootReasonSysctlRegistered, true, release);
11444 	}
11445 	WAKEEVENT_UNLOCK();
11446 }
11447 
11448 //******************************************************************************
11449 // claimSystemShutdownEvent
11450 //
11451 // For drivers to claim a system shutdown event on the ensuing boot.
11452 //******************************************************************************
11453 
11454 void
11455 IOPMrootDomain::claimSystemShutdownEvent(
11456 	IOService *              device,
11457 	IOOptionBits             flags,
11458 	const char *             reason,
11459 	OSObject *               details )
11460 {
11461 	if (!device || !reason) {
11462 		return;
11463 	}
11464 
11465 	DEBUG_LOG("claimSystemShutdownEvent(%s, %s, 0x%x)\n", reason, device->getName(), (uint32_t) flags);
11466 #if DEVELOPMENT || DEBUG
11467 	record_system_event(SYSTEM_EVENT_TYPE_INFO,
11468 	    SYSTEM_EVENT_SUBSYSTEM_PMRD,
11469 	    "Report System Shutdown Cause From Previous Boot",
11470 	    "Reason: %s Flags: 0x%x Device: %s",
11471 	    reason,
11472 	    (int)flags,
11473 	    device->getName()
11474 	    );
11475 #endif /* DEVELOPMENT || DEBUG */
11476 	WAKEEVENT_LOCK();
11477 	if (gShutdownReasonString[0] != '\0') {
11478 		strlcat(gShutdownReasonString, " ", sizeof(gShutdownReasonString));
11479 	}
11480 	strlcat(gShutdownReasonString, reason, sizeof(gShutdownReasonString));
11481 
11482 	if (details) {
11483 		OSDictionary *dict = OSDynamicCast(OSDictionary, details);
11484 		if (dict) {
11485 			OSSharedPtr<OSString> sharedKey = OSString::withCString(kIOPMRootDomainShutdownTime);
11486 			if (sharedKey) {
11487 				OSNumber *num = OSDynamicCast(OSNumber, dict->getObject(sharedKey.get()));
11488 				if (num) {
11489 					gShutdownTime = (uint64_t)(num->unsigned64BitValue());
11490 				}
11491 			}
11492 		}
11493 	}
11494 
11495 	gShutdownReasonSysctlRegistered = true;
11496 	WAKEEVENT_UNLOCK();
11497 }
11498 
11499 //******************************************************************************
11500 // requestRunMode
11501 //
11502 // For clients to request a LPW run mode. Only full wake is supported currently.
11503 //******************************************************************************
11504 
11505 IOReturn
11506 IOPMrootDomain::requestRunMode(uint64_t runModeMask)
11507 {
11508 	// We only support requesting full wake at the moment
11509 	if (runModeMask == kIOPMRunModeFullWake) {
11510 		pmPowerStateQueue->submitPowerEvent(kPowerEventRunModeRequest, NULL, runModeMask);
11511 		return kIOReturnSuccess;
11512 	}
11513 	return kIOReturnUnsupported;
11514 }
11515 
11516 IOReturn
11517 IOPMrootDomain::handleRequestRunMode(uint64_t runModeMask)
11518 {
11519 	// TODO: Replace with run mode logic when implemented
11520 	IOReturn ret = kIOReturnUnsupported;
11521 
11522 	// We only support requesting full wake at the moment
11523 	if (runModeMask == kIOPMRunModeFullWake) {
11524 		// A simple CPS should suffice for now
11525 		changePowerStateWithTagToPriv(ON_STATE, kCPSReasonEvaluatePolicy);
11526 		ret = kIOReturnSuccess;
11527 	}
11528 
11529 	DLOG("%s: mask %llx ret %x\n", __func__, runModeMask, ret);
11530 	return ret;
11531 }
11532 
11533 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11534 
11535 // MARK: -
11536 // MARK: PMSettingHandle
11537 
11538 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
11539 
11540 void
11541 PMSettingHandle::free( void )
11542 {
11543 	if (pmso) {
11544 		pmso->clientHandleFreed();
11545 		pmso->release();
11546 		pmso = NULL;
11547 	}
11548 
11549 	OSObject::free();
11550 }
11551 
11552 // MARK: -
11553 // MARK: PMSettingObject
11554 
11555 #undef super
11556 #define super OSObject
11557 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
11558 
11559 /*
11560  * Static constructor/initializer for PMSettingObject
11561  */
11562 PMSettingObject *PMSettingObject::pmSettingObject(
11563 	IOPMrootDomain                      * parent_arg,
11564 	IOPMSettingControllerCallback       handler_arg,
11565 	OSObject                            * target_arg,
11566 	uintptr_t                           refcon_arg,
11567 	uint32_t                            supportedPowerSources,
11568 	const OSSymbol *                    settings[],
11569 	OSObject                            * *handle_obj)
11570 {
11571 	uint32_t                            settingCount = 0;
11572 	PMSettingObject                     *pmso = NULL;
11573 	PMSettingHandle                     *pmsh = NULL;
11574 
11575 	if (!parent_arg || !handler_arg || !settings || !handle_obj) {
11576 		return NULL;
11577 	}
11578 
11579 	// count OSSymbol entries in NULL terminated settings array
11580 	while (settings[settingCount]) {
11581 		settingCount++;
11582 	}
11583 	if (0 == settingCount) {
11584 		return NULL;
11585 	}
11586 
11587 	pmso = new PMSettingObject;
11588 	if (!pmso || !pmso->init()) {
11589 		goto fail;
11590 	}
11591 
11592 	pmsh = new PMSettingHandle;
11593 	if (!pmsh || !pmsh->init()) {
11594 		goto fail;
11595 	}
11596 
11597 	queue_init(&pmso->calloutQueue);
11598 	pmso->parent       = parent_arg;
11599 	pmso->func         = handler_arg;
11600 	pmso->target       = target_arg;
11601 	pmso->refcon       = refcon_arg;
11602 	pmso->settingCount = settingCount;
11603 
11604 	pmso->retain(); // handle holds a retain on pmso
11605 	pmsh->pmso = pmso;
11606 	pmso->pmsh = pmsh;
11607 
11608 	pmso->publishedFeatureID = OSDataAllocation<uint32_t>(settingCount, OSAllocateMemory);
11609 	if (pmso->publishedFeatureID) {
11610 		for (unsigned int i = 0; i < settingCount; i++) {
11611 			// Since there is now at least one listener to this setting, publish
11612 			// PM root domain support for it.
11613 			parent_arg->publishPMSetting( settings[i],
11614 			    supportedPowerSources, &pmso->publishedFeatureID[i] );
11615 		}
11616 	}
11617 
11618 	*handle_obj = pmsh;
11619 	return pmso;
11620 
11621 fail:
11622 	if (pmso) {
11623 		pmso->release();
11624 	}
11625 	if (pmsh) {
11626 		pmsh->release();
11627 	}
11628 	return NULL;
11629 }
11630 
11631 void
11632 PMSettingObject::free( void )
11633 {
11634 	if (publishedFeatureID) {
11635 		for (const auto& featureID : publishedFeatureID) {
11636 			if (featureID) {
11637 				parent->removePublishedFeature( featureID );
11638 			}
11639 		}
11640 
11641 		publishedFeatureID = {};
11642 	}
11643 
11644 	super::free();
11645 }
11646 
11647 IOReturn
11648 PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
11649 {
11650 	return (*func)(target, type, object, refcon);
11651 }
11652 
11653 void
11654 PMSettingObject::clientHandleFreed( void )
11655 {
11656 	parent->deregisterPMSettingObject(this);
11657 }
11658 
11659 // MARK: -
11660 // MARK: PMAssertionsTracker
11661 
11662 //*********************************************************************************
11663 //*********************************************************************************
11664 //*********************************************************************************
11665 // class PMAssertionsTracker Implementation
11666 
11667 #define kAssertUniqueIDStart    500
11668 
11669 PMAssertionsTracker *
11670 PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
11671 {
11672 	PMAssertionsTracker    *me;
11673 
11674 	me = new PMAssertionsTracker;
11675 	if (!me || !me->init()) {
11676 		if (me) {
11677 			me->release();
11678 		}
11679 		return NULL;
11680 	}
11681 
11682 	me->owner = rootDomain;
11683 	me->issuingUniqueID = kAssertUniqueIDStart;
11684 	me->assertionsArray = OSArray::withCapacity(5);
11685 	me->assertionsKernel = 0;
11686 	me->assertionsUser = 0;
11687 	me->assertionsCombined = 0;
11688 	me->assertionsArrayLock = IOLockAlloc();
11689 	me->tabulateProducerCount = me->tabulateConsumerCount = 0;
11690 
11691 	assert(me->assertionsArray);
11692 	assert(me->assertionsArrayLock);
11693 
11694 	return me;
11695 }
11696 
11697 /* tabulate
11698  * - Update assertionsKernel to reflect the state of all
11699  * assertions in the kernel.
11700  * - Update assertionsCombined to reflect both kernel & user space.
11701  */
11702 void
11703 PMAssertionsTracker::tabulate(void)
11704 {
11705 	int i;
11706 	int count;
11707 	const PMAssertStruct *_a = nullptr;
11708 	OSValueObject<PMAssertStruct> *_d = nullptr;
11709 
11710 	IOPMDriverAssertionType oldKernel = assertionsKernel;
11711 	IOPMDriverAssertionType oldCombined = assertionsCombined;
11712 
11713 	ASSERT_GATED();
11714 
11715 	assertionsKernel = 0;
11716 	assertionsCombined = 0;
11717 
11718 	if (!assertionsArray) {
11719 		return;
11720 	}
11721 
11722 	if ((count = assertionsArray->getCount())) {
11723 		for (i = 0; i < count; i++) {
11724 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11725 			if (_d) {
11726 				_a = _d->getBytesNoCopy();
11727 				if (_a && (kIOPMDriverAssertionLevelOn == _a->level)) {
11728 					assertionsKernel |= _a->assertionBits;
11729 				}
11730 			}
11731 		}
11732 	}
11733 
11734 	tabulateProducerCount++;
11735 	assertionsCombined = assertionsKernel | assertionsUser;
11736 
11737 	if ((assertionsKernel != oldKernel) ||
11738 	    (assertionsCombined != oldCombined)) {
11739 		owner->evaluateAssertions(assertionsCombined, oldCombined);
11740 	}
11741 }
11742 
11743 void
11744 PMAssertionsTracker::updateCPUBitAccounting( PMAssertStruct *assertStruct )
11745 {
11746 	AbsoluteTime now;
11747 	uint64_t     nsec;
11748 
11749 	if (((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) == 0) ||
11750 	    (assertStruct->assertCPUStartTime == 0)) {
11751 		return;
11752 	}
11753 
11754 	now = mach_absolute_time();
11755 	SUB_ABSOLUTETIME(&now, &assertStruct->assertCPUStartTime);
11756 	absolutetime_to_nanoseconds(now, &nsec);
11757 	assertStruct->assertCPUDuration += nsec;
11758 	assertStruct->assertCPUStartTime = 0;
11759 
11760 	if (assertStruct->assertCPUDuration > maxAssertCPUDuration) {
11761 		maxAssertCPUDuration = assertStruct->assertCPUDuration;
11762 		maxAssertCPUEntryId = assertStruct->registryEntryID;
11763 	}
11764 }
11765 
11766 void
11767 PMAssertionsTracker::reportCPUBitAccounting( void )
11768 {
11769 	const PMAssertStruct *_a = nullptr;
11770 	OSValueObject<PMAssertStruct> *_d = nullptr;
11771 	int            i, count;
11772 	AbsoluteTime   now;
11773 	uint64_t       nsec;
11774 
11775 	ASSERT_GATED();
11776 
11777 	// Account for drivers that are still holding the CPU assertion
11778 	if (assertionsKernel & kIOPMDriverAssertionCPUBit) {
11779 		now = mach_absolute_time();
11780 		if ((count = assertionsArray->getCount())) {
11781 			for (i = 0; i < count; i++) {
11782 				_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11783 				if (_d) {
11784 					_a = _d->getBytesNoCopy();
11785 					if ((_a->assertionBits & kIOPMDriverAssertionCPUBit) &&
11786 					    (_a->level == kIOPMDriverAssertionLevelOn) &&
11787 					    (_a->assertCPUStartTime != 0)) {
11788 						// Don't modify PMAssertStruct, leave that
11789 						// for updateCPUBitAccounting()
11790 						SUB_ABSOLUTETIME(&now, &_a->assertCPUStartTime);
11791 						absolutetime_to_nanoseconds(now, &nsec);
11792 						nsec += _a->assertCPUDuration;
11793 						if (nsec > maxAssertCPUDuration) {
11794 							maxAssertCPUDuration = nsec;
11795 							maxAssertCPUEntryId = _a->registryEntryID;
11796 						}
11797 					}
11798 				}
11799 			}
11800 		}
11801 	}
11802 
11803 	if (maxAssertCPUDuration) {
11804 		DLOG("cpu assertion held for %llu ms by 0x%llx\n",
11805 		    (maxAssertCPUDuration / NSEC_PER_MSEC), maxAssertCPUEntryId);
11806 	}
11807 
11808 	maxAssertCPUDuration = 0;
11809 	maxAssertCPUEntryId = 0;
11810 }
11811 
11812 void
11813 PMAssertionsTracker::publishProperties( void )
11814 {
11815 	OSSharedPtr<OSArray>             assertionsSummary;
11816 
11817 	if (tabulateConsumerCount != tabulateProducerCount) {
11818 		IOLockLock(assertionsArrayLock);
11819 
11820 		tabulateConsumerCount = tabulateProducerCount;
11821 
11822 		/* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
11823 		 */
11824 		assertionsSummary = copyAssertionsArray();
11825 		if (assertionsSummary) {
11826 			owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary.get());
11827 		} else {
11828 			owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
11829 		}
11830 
11831 		/* Publish the IOPMrootDomain property "DriverPMAssertions"
11832 		 */
11833 		owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
11834 
11835 		IOLockUnlock(assertionsArrayLock);
11836 	}
11837 }
11838 
11839 PMAssertStruct *
11840 PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
11841 {
11842 	PMAssertStruct      *_a = NULL;
11843 	OSValueObject<PMAssertStruct> *_d = nullptr;
11844 	int                 found = -1;
11845 	int                 count = 0;
11846 	int                 i = 0;
11847 
11848 	if (assertionsArray
11849 	    && (count = assertionsArray->getCount())) {
11850 		for (i = 0; i < count; i++) {
11851 			_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
11852 			if (_d) {
11853 				_a = _d->getMutableBytesNoCopy();
11854 				if (_a && (_id == _a->id)) {
11855 					found = i;
11856 					break;
11857 				}
11858 			}
11859 		}
11860 	}
11861 
11862 	if (-1 == found) {
11863 		return NULL;
11864 	} else {
11865 		if (index) {
11866 			*index = found;
11867 		}
11868 		return _a;
11869 	}
11870 }
11871 
11872 /* PMAssertionsTracker::handleCreateAssertion
11873  * Perform assertion work on the PM workloop. Do not call directly.
11874  */
11875 IOReturn
11876 PMAssertionsTracker::handleCreateAssertion(OSValueObject<PMAssertStruct> *newAssertion)
11877 {
11878 	PMAssertStruct *assertStruct = nullptr;
11879 
11880 	ASSERT_GATED();
11881 
11882 	if (newAssertion) {
11883 		IOLockLock(assertionsArrayLock);
11884 		assertStruct = newAssertion->getMutableBytesNoCopy();
11885 		if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11886 		    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11887 			assertStruct->assertCPUStartTime = mach_absolute_time();
11888 		}
11889 		assertionsArray->setObject(newAssertion);
11890 		IOLockUnlock(assertionsArrayLock);
11891 		newAssertion->release();
11892 
11893 		tabulate();
11894 	}
11895 	return kIOReturnSuccess;
11896 }
11897 
11898 /* PMAssertionsTracker::createAssertion
11899  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
11900  * appropiate.
11901  */
11902 IOReturn
11903 PMAssertionsTracker::createAssertion(
11904 	IOPMDriverAssertionType which,
11905 	IOPMDriverAssertionLevel level,
11906 	IOService *serviceID,
11907 	const char *whoItIs,
11908 	IOPMDriverAssertionID *outID)
11909 {
11910 	OSSharedPtr<OSValueObject<PMAssertStruct> > dataStore;
11911 	PMAssertStruct  track;
11912 
11913 	// Warning: trillions and trillions of created assertions may overflow the unique ID.
11914 	track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
11915 	track.level = level;
11916 	track.assertionBits = which;
11917 
11918 	// NB: ownerString is explicitly managed by PMAssertStruct
11919 	// it will be released in `handleReleaseAssertion' below
11920 	track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs).detach():nullptr;
11921 	track.ownerService = serviceID;
11922 	track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
11923 	track.modifiedTime = 0;
11924 	pmEventTimeStamp(&track.createdTime);
11925 	track.assertCPUStartTime = 0;
11926 	track.assertCPUDuration = 0;
11927 
11928 	dataStore = OSValueObjectWithValue(track);
11929 	if (!dataStore) {
11930 		if (track.ownerString) {
11931 			track.ownerString->release();
11932 			track.ownerString = NULL;
11933 		}
11934 		return kIOReturnNoMemory;
11935 	}
11936 
11937 	*outID = track.id;
11938 
11939 	if (owner && owner->pmPowerStateQueue) {
11940 		// queue action is responsible for releasing dataStore
11941 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore.detach());
11942 	}
11943 
11944 	return kIOReturnSuccess;
11945 }
11946 
11947 /* PMAssertionsTracker::handleReleaseAssertion
11948  * Runs in PM workloop. Do not call directly.
11949  */
11950 IOReturn
11951 PMAssertionsTracker::handleReleaseAssertion(
11952 	IOPMDriverAssertionID _id)
11953 {
11954 	ASSERT_GATED();
11955 
11956 	int             index;
11957 	PMAssertStruct  *assertStruct = detailsForID(_id, &index);
11958 
11959 	if (!assertStruct) {
11960 		return kIOReturnNotFound;
11961 	}
11962 
11963 	IOLockLock(assertionsArrayLock);
11964 
11965 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
11966 	    (assertStruct->level == kIOPMDriverAssertionLevelOn)) {
11967 		updateCPUBitAccounting(assertStruct);
11968 	}
11969 
11970 	if (assertStruct->ownerString) {
11971 		assertStruct->ownerString->release();
11972 		assertStruct->ownerString = NULL;
11973 	}
11974 
11975 	assertionsArray->removeObject(index);
11976 	IOLockUnlock(assertionsArrayLock);
11977 
11978 	tabulate();
11979 	return kIOReturnSuccess;
11980 }
11981 
11982 /* PMAssertionsTracker::releaseAssertion
11983  * Releases an assertion and affects system behavior if appropiate.
11984  * Actual work happens on PM workloop.
11985  */
11986 IOReturn
11987 PMAssertionsTracker::releaseAssertion(
11988 	IOPMDriverAssertionID _id)
11989 {
11990 	if (owner && owner->pmPowerStateQueue) {
11991 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, NULL, _id);
11992 	}
11993 	return kIOReturnSuccess;
11994 }
11995 
11996 /* PMAssertionsTracker::handleSetAssertionLevel
11997  * Runs in PM workloop. Do not call directly.
11998  */
11999 IOReturn
12000 PMAssertionsTracker::handleSetAssertionLevel(
12001 	IOPMDriverAssertionID    _id,
12002 	IOPMDriverAssertionLevel _level)
12003 {
12004 	PMAssertStruct      *assertStruct = detailsForID(_id, NULL);
12005 
12006 	ASSERT_GATED();
12007 
12008 	if (!assertStruct) {
12009 		return kIOReturnNotFound;
12010 	}
12011 
12012 	IOLockLock(assertionsArrayLock);
12013 	pmEventTimeStamp(&assertStruct->modifiedTime);
12014 	if ((assertStruct->assertionBits & kIOPMDriverAssertionCPUBit) &&
12015 	    (assertStruct->level != _level)) {
12016 		if (_level == kIOPMDriverAssertionLevelOn) {
12017 			assertStruct->assertCPUStartTime = mach_absolute_time();
12018 		} else {
12019 			updateCPUBitAccounting(assertStruct);
12020 		}
12021 	}
12022 	assertStruct->level = _level;
12023 	IOLockUnlock(assertionsArrayLock);
12024 
12025 	tabulate();
12026 	return kIOReturnSuccess;
12027 }
12028 
12029 /* PMAssertionsTracker::setAssertionLevel
12030  */
12031 IOReturn
12032 PMAssertionsTracker::setAssertionLevel(
12033 	IOPMDriverAssertionID    _id,
12034 	IOPMDriverAssertionLevel _level)
12035 {
12036 	if (owner && owner->pmPowerStateQueue) {
12037 		owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
12038 		    (void *)(uintptr_t)_level, _id);
12039 	}
12040 
12041 	return kIOReturnSuccess;
12042 }
12043 
12044 IOReturn
12045 PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
12046 {
12047 	IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
12048 
12049 	ASSERT_GATED();
12050 
12051 	if (new_user_levels != assertionsUser) {
12052 		DLOG("assertionsUser 0x%llx->0x%llx\n", assertionsUser, new_user_levels);
12053 		assertionsUser = new_user_levels;
12054 	}
12055 
12056 	tabulate();
12057 	return kIOReturnSuccess;
12058 }
12059 
12060 IOReturn
12061 PMAssertionsTracker::setUserAssertionLevels(
12062 	IOPMDriverAssertionType new_user_levels)
12063 {
12064 	if (gIOPMWorkLoop) {
12065 		gIOPMWorkLoop->runAction(
12066 			OSMemberFunctionCast(
12067 				IOWorkLoop::Action,
12068 				this,
12069 				&PMAssertionsTracker::handleSetUserAssertionLevels),
12070 			this,
12071 			(void *) &new_user_levels, NULL, NULL, NULL);
12072 	}
12073 
12074 	return kIOReturnSuccess;
12075 }
12076 
12077 
12078 OSSharedPtr<OSArray>
12079 PMAssertionsTracker::copyAssertionsArray(void)
12080 {
12081 	int count;
12082 	int i;
12083 	OSSharedPtr<OSArray>     outArray = NULL;
12084 
12085 	if (!assertionsArray || (0 == (count = assertionsArray->getCount()))) {
12086 		goto exit;
12087 	}
12088 	outArray = OSArray::withCapacity(count);
12089 	if (!outArray) {
12090 		goto exit;
12091 	}
12092 
12093 	for (i = 0; i < count; i++) {
12094 		const PMAssertStruct *_a = nullptr;
12095 		OSValueObject<PMAssertStruct> *_d = nullptr;
12096 		OSSharedPtr<OSDictionary>    details;
12097 
12098 		_d = OSDynamicCast(OSValueObject<PMAssertStruct>, assertionsArray->getObject(i));
12099 		if (_d && (_a = _d->getBytesNoCopy())) {
12100 			OSSharedPtr<OSNumber>        _n;
12101 
12102 			details = OSDictionary::withCapacity(7);
12103 			if (!details) {
12104 				continue;
12105 			}
12106 
12107 			outArray->setObject(details.get());
12108 
12109 			_n = OSNumber::withNumber(_a->id, 64);
12110 			if (_n) {
12111 				details->setObject(kIOPMDriverAssertionIDKey, _n.get());
12112 			}
12113 			_n = OSNumber::withNumber(_a->createdTime, 64);
12114 			if (_n) {
12115 				details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n.get());
12116 			}
12117 			_n = OSNumber::withNumber(_a->modifiedTime, 64);
12118 			if (_n) {
12119 				details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n.get());
12120 			}
12121 			_n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
12122 			if (_n) {
12123 				details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n.get());
12124 			}
12125 			_n = OSNumber::withNumber(_a->level, 64);
12126 			if (_n) {
12127 				details->setObject(kIOPMDriverAssertionLevelKey, _n.get());
12128 			}
12129 			_n = OSNumber::withNumber(_a->assertionBits, 64);
12130 			if (_n) {
12131 				details->setObject(kIOPMDriverAssertionAssertedKey, _n.get());
12132 			}
12133 
12134 			if (_a->ownerString) {
12135 				details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
12136 			}
12137 		}
12138 	}
12139 
12140 exit:
12141 	return os::move(outArray);
12142 }
12143 
12144 IOPMDriverAssertionType
12145 PMAssertionsTracker::getActivatedAssertions(void)
12146 {
12147 	return assertionsCombined;
12148 }
12149 
12150 IOPMDriverAssertionLevel
12151 PMAssertionsTracker::getAssertionLevel(
12152 	IOPMDriverAssertionType type)
12153 {
12154 	// FIXME: unused and also wrong
12155 	if (type && ((type & assertionsKernel) == assertionsKernel)) {
12156 		return kIOPMDriverAssertionLevelOn;
12157 	} else {
12158 		return kIOPMDriverAssertionLevelOff;
12159 	}
12160 }
12161 
12162 //*********************************************************************************
12163 //*********************************************************************************
12164 //*********************************************************************************
12165 
12166 
12167 static void
12168 pmEventTimeStamp(uint64_t *recordTS)
12169 {
12170 	clock_sec_t     tsec;
12171 	clock_usec_t    tusec;
12172 
12173 	if (!recordTS) {
12174 		return;
12175 	}
12176 
12177 	// We assume tsec fits into 32 bits; 32 bits holds enough
12178 	// seconds for 136 years since the epoch in 1970.
12179 	clock_get_calendar_microtime(&tsec, &tusec);
12180 
12181 
12182 	// Pack the sec & microsec calendar time into a uint64_t, for fun.
12183 	*recordTS = 0;
12184 	*recordTS |= (uint32_t)tusec;
12185 	*recordTS |= ((uint64_t)tsec << 32);
12186 
12187 	return;
12188 }
12189 
12190 // MARK: -
12191 // MARK: IORootParent
12192 
12193 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12194 
12195 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
12196 
12197 // The reason that root domain needs a root parent is to facilitate demand
12198 // sleep, since a power change from the root parent cannot be vetoed.
12199 //
12200 // The above statement is no longer true since root domain now performs
12201 // demand sleep using overrides. But root parent remains to avoid changing
12202 // the power tree stacking. Root parent is parked at the max power state.
12203 
12204 
12205 static IOPMPowerState patriarchPowerStates[2] =
12206 {
12207 	{.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER },
12208 	{.version = kIOPMPowerStateVersion1, .outputPowerCharacter = ON_POWER }
12209 };
12210 
12211 void
12212 IORootParent::initialize( void )
12213 {
12214 
12215 	gIOPMPSExternalConnectedKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalConnectedKey);
12216 	gIOPMPSExternalChargeCapableKey = OSSymbol::withCStringNoCopy(kIOPMPSExternalChargeCapableKey);
12217 	gIOPMPSBatteryInstalledKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryInstalledKey);
12218 	gIOPMPSIsChargingKey = OSSymbol::withCStringNoCopy(kIOPMPSIsChargingKey);
12219 	gIOPMPSAtWarnLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtWarnLevelKey);
12220 	gIOPMPSAtCriticalLevelKey = OSSymbol::withCStringNoCopy(kIOPMPSAtCriticalLevelKey);
12221 	gIOPMPSCurrentCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSCurrentCapacityKey);
12222 	gIOPMPSMaxCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxCapacityKey);
12223 	gIOPMPSDesignCapacityKey = OSSymbol::withCStringNoCopy(kIOPMPSDesignCapacityKey);
12224 	gIOPMPSTimeRemainingKey = OSSymbol::withCStringNoCopy(kIOPMPSTimeRemainingKey);
12225 	gIOPMPSAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAmperageKey);
12226 	gIOPMPSVoltageKey = OSSymbol::withCStringNoCopy(kIOPMPSVoltageKey);
12227 	gIOPMPSCycleCountKey = OSSymbol::withCStringNoCopy(kIOPMPSCycleCountKey);
12228 	gIOPMPSMaxErrKey = OSSymbol::withCStringNoCopy(kIOPMPSMaxErrKey);
12229 	gIOPMPSAdapterInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterInfoKey);
12230 	gIOPMPSLocationKey = OSSymbol::withCStringNoCopy(kIOPMPSLocationKey);
12231 	gIOPMPSErrorConditionKey = OSSymbol::withCStringNoCopy(kIOPMPSErrorConditionKey);
12232 	gIOPMPSManufacturerKey = OSSymbol::withCStringNoCopy(kIOPMPSManufacturerKey);
12233 	gIOPMPSManufactureDateKey = OSSymbol::withCStringNoCopy(kIOPMPSManufactureDateKey);
12234 	gIOPMPSModelKey = OSSymbol::withCStringNoCopy(kIOPMPSModelKey);
12235 	gIOPMPSSerialKey = OSSymbol::withCStringNoCopy(kIOPMPSSerialKey);
12236 	gIOPMPSLegacyBatteryInfoKey = OSSymbol::withCStringNoCopy(kIOPMPSLegacyBatteryInfoKey);
12237 	gIOPMPSBatteryHealthKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryHealthKey);
12238 	gIOPMPSHealthConfidenceKey = OSSymbol::withCStringNoCopy(kIOPMPSHealthConfidenceKey);
12239 	gIOPMPSCapacityEstimatedKey = OSSymbol::withCStringNoCopy(kIOPMPSCapacityEstimatedKey);
12240 	gIOPMPSBatteryChargeStatusKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryChargeStatusKey);
12241 	gIOPMPSBatteryTemperatureKey = OSSymbol::withCStringNoCopy(kIOPMPSBatteryTemperatureKey);
12242 	gIOPMPSAdapterDetailsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsKey);
12243 	gIOPMPSChargerConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSChargerConfigurationKey);
12244 	gIOPMPSAdapterDetailsIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsIDKey);
12245 	gIOPMPSAdapterDetailsWattsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsWattsKey);
12246 	gIOPMPSAdapterDetailsRevisionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsRevisionKey);
12247 	gIOPMPSAdapterDetailsSerialNumberKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSerialNumberKey);
12248 	gIOPMPSAdapterDetailsFamilyKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsFamilyKey);
12249 	gIOPMPSAdapterDetailsAmperageKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsAmperageKey);
12250 	gIOPMPSAdapterDetailsDescriptionKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsDescriptionKey);
12251 	gIOPMPSAdapterDetailsPMUConfigurationKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsPMUConfigurationKey);
12252 	gIOPMPSAdapterDetailsSourceIDKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSourceIDKey);
12253 	gIOPMPSAdapterDetailsErrorFlagsKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsErrorFlagsKey);
12254 	gIOPMPSAdapterDetailsSharedSourceKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsSharedSourceKey);
12255 	gIOPMPSAdapterDetailsCloakedKey = OSSymbol::withCStringNoCopy(kIOPMPSAdapterDetailsCloakedKey);
12256 	gIOPMPSInvalidWakeSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSInvalidWakeSecondsKey);
12257 	gIOPMPSPostChargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostChargeWaitSecondsKey);
12258 	gIOPMPSPostDishargeWaitSecondsKey = OSSymbol::withCStringNoCopy(kIOPMPSPostDishargeWaitSecondsKey);
12259 }
12260 
12261 bool
12262 IORootParent::start( IOService * nub )
12263 {
12264 	IOService::start(nub);
12265 	attachToParent( getRegistryRoot(), gIOPowerPlane );
12266 	PMinit();
12267 	registerPowerDriver(this, patriarchPowerStates, 2);
12268 	makeUsable();
12269 	return true;
12270 }
12271 
12272 void
12273 IORootParent::shutDownSystem( void )
12274 {
12275 }
12276 
12277 void
12278 IORootParent::restartSystem( void )
12279 {
12280 }
12281 
12282 void
12283 IORootParent::sleepSystem( void )
12284 {
12285 }
12286 
12287 void
12288 IORootParent::dozeSystem( void )
12289 {
12290 }
12291 
12292 void
12293 IORootParent::sleepToDoze( void )
12294 {
12295 }
12296 
12297 void
12298 IORootParent::wakeSystem( void )
12299 {
12300 }
12301 
12302 OSSharedPtr<OSObject>
12303 IORootParent::copyProperty( const char * aKey) const
12304 {
12305 	return IOService::copyProperty(aKey);
12306 }
12307 
12308 uint32_t
12309 IOPMrootDomain::getWatchdogTimeout()
12310 {
12311 	if (gSwdSleepWakeTimeout) {
12312 		gSwdSleepTimeout = gSwdWakeTimeout = gSwdSleepWakeTimeout;
12313 	}
12314 	if ((pmTracer->getTracePhase() < kIOPMTracePointSystemSleep) ||
12315 	    (pmTracer->getTracePhase() == kIOPMTracePointDarkWakeEntry)) {
12316 		return gSwdSleepTimeout ? gSwdSleepTimeout : WATCHDOG_SLEEP_TIMEOUT;
12317 	} else {
12318 		return gSwdWakeTimeout ? gSwdWakeTimeout : WATCHDOG_WAKE_TIMEOUT;
12319 	}
12320 }
12321 
12322 
12323 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm64__) && HIBERNATION)
12324 IOReturn
12325 IOPMrootDomain::restartWithStackshot()
12326 {
12327 	takeStackshot(true);
12328 
12329 	return kIOReturnSuccess;
12330 }
12331 
12332 void
12333 IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
12334 {
12335 	takeStackshot(wdogTrigger);
12336 }
12337 
12338 void
12339 IOPMrootDomain::tracePhase2String(uint32_t tracePhase, const char **phaseString, const char **description)
12340 {
12341 	switch (tracePhase) {
12342 	case kIOPMTracePointSleepStarted:
12343 		*phaseString = "kIOPMTracePointSleepStarted";
12344 		*description = "starting sleep";
12345 		break;
12346 
12347 	case kIOPMTracePointSleepApplications:
12348 		*phaseString = "kIOPMTracePointSleepApplications";
12349 		*description = "notifying applications";
12350 		break;
12351 
12352 	case kIOPMTracePointSleepPriorityClients:
12353 		*phaseString = "kIOPMTracePointSleepPriorityClients";
12354 		*description = "notifying clients about upcoming system capability changes";
12355 		break;
12356 
12357 	case kIOPMTracePointSleepWillChangeInterests:
12358 		*phaseString = "kIOPMTracePointSleepWillChangeInterests";
12359 		*description = "creating hibernation file or while calling rootDomain's clients about upcoming rootDomain's state changes";
12360 		break;
12361 
12362 	case kIOPMTracePointSleepPowerPlaneDrivers:
12363 		*phaseString = "kIOPMTracePointSleepPowerPlaneDrivers";
12364 		*description = "calling power state change callbacks";
12365 		break;
12366 
12367 	case kIOPMTracePointSleepDidChangeInterests:
12368 		*phaseString = "kIOPMTracePointSleepDidChangeInterests";
12369 		*description = "calling rootDomain's clients about rootDomain's state changes";
12370 		break;
12371 
12372 	case kIOPMTracePointSleepCapabilityClients:
12373 		*phaseString = "kIOPMTracePointSleepCapabilityClients";
12374 		*description = "notifying clients about current system capabilities";
12375 		break;
12376 
12377 	case kIOPMTracePointSleepPlatformActions:
12378 		*phaseString = "kIOPMTracePointSleepPlatformActions";
12379 		*description = "calling Quiesce/Sleep action callbacks";
12380 		break;
12381 
12382 	case kIOPMTracePointSleepCPUs:
12383 	{
12384 		*phaseString = "kIOPMTracePointSleepCPUs";
12385 #if defined(__i386__) || defined(__x86_64__)
12386 		/*
12387 		 * We cannot use the getCPUNumber() method to get the cpu number, since
12388 		 * that cpu number is unrelated to the cpu number we need (we need the cpu
12389 		 * number as enumerated by the scheduler, NOT the CPU number enumerated
12390 		 * by ACPIPlatform as the CPUs are enumerated in MADT order).
12391 		 * Instead, pass the Mach processor pointer associated with the current
12392 		 * shutdown target so its associated cpu_id can be used in
12393 		 * processor_to_datastring.
12394 		 */
12395 		if (currentShutdownTarget != NULL &&
12396 		    currentShutdownTarget->getMachProcessor() != NULL) {
12397 			const char *sbuf = processor_to_datastring("halting all non-boot CPUs",
12398 			    currentShutdownTarget->getMachProcessor());
12399 			*description = sbuf;
12400 		} else {
12401 			*description = "halting all non-boot CPUs";
12402 		}
12403 #else
12404 		*description = "halting all non-boot CPUs";
12405 #endif
12406 		break;
12407 	}
12408 	case kIOPMTracePointSleepPlatformDriver:
12409 		*phaseString = "kIOPMTracePointSleepPlatformDriver";
12410 		*description = "executing platform specific code";
12411 		break;
12412 
12413 	case kIOPMTracePointHibernate:
12414 		*phaseString = "kIOPMTracePointHibernate";
12415 		*description = "writing the hibernation image";
12416 		break;
12417 
12418 	case kIOPMTracePointSystemSleep:
12419 		*phaseString = "kIOPMTracePointSystemSleep";
12420 		*description = "in EFI/Bootrom after last point of entry to sleep";
12421 		break;
12422 
12423 	case kIOPMTracePointWakePlatformDriver:
12424 		*phaseString = "kIOPMTracePointWakePlatformDriver";
12425 		*description = "executing platform specific code";
12426 		break;
12427 
12428 
12429 	case kIOPMTracePointWakePlatformActions:
12430 		*phaseString = "kIOPMTracePointWakePlatformActions";
12431 		*description = "calling Wake action callbacks";
12432 		break;
12433 
12434 	case kIOPMTracePointWakeCPUs:
12435 		*phaseString = "kIOPMTracePointWakeCPUs";
12436 		*description = "starting non-boot CPUs";
12437 		break;
12438 
12439 	case kIOPMTracePointWakeWillPowerOnClients:
12440 		*phaseString = "kIOPMTracePointWakeWillPowerOnClients";
12441 		*description = "sending kIOMessageSystemWillPowerOn message to kernel and userspace clients";
12442 		break;
12443 
12444 	case kIOPMTracePointWakeWillChangeInterests:
12445 		*phaseString = "kIOPMTracePointWakeWillChangeInterests";
12446 		*description = "calling rootDomain's clients about upcoming rootDomain's state changes";
12447 		break;
12448 
12449 	case kIOPMTracePointWakeDidChangeInterests:
12450 		*phaseString = "kIOPMTracePointWakeDidChangeInterests";
12451 		*description = "calling rootDomain's clients about completed rootDomain's state changes";
12452 		break;
12453 
12454 	case kIOPMTracePointWakePowerPlaneDrivers:
12455 		*phaseString = "kIOPMTracePointWakePowerPlaneDrivers";
12456 		*description = "calling power state change callbacks";
12457 		break;
12458 
12459 	case kIOPMTracePointWakeCapabilityClients:
12460 		*phaseString = "kIOPMTracePointWakeCapabilityClients";
12461 		*description = "informing clients about current system capabilities";
12462 		break;
12463 
12464 	case kIOPMTracePointWakeApplications:
12465 		*phaseString = "kIOPMTracePointWakeApplications";
12466 		*description = "sending asynchronous kIOMessageSystemHasPoweredOn message to userspace clients";
12467 		break;
12468 
12469 	case kIOPMTracePointDarkWakeEntry:
12470 		*phaseString = "kIOPMTracePointDarkWakeEntry";
12471 		*description = "entering darkwake on way to sleep";
12472 		break;
12473 
12474 	case kIOPMTracePointDarkWakeExit:
12475 		*phaseString = "kIOPMTracePointDarkWakeExit";
12476 		*description = "entering fullwake from darkwake";
12477 		break;
12478 
12479 	default:
12480 		*phaseString = NULL;
12481 		*description = NULL;
12482 	}
12483 }
12484 
12485 void
12486 IOPMrootDomain::saveFailureData2File()
12487 {
12488 	unsigned int len = 0;
12489 	char  failureStr[512];
12490 	errno_t error;
12491 	char *outbuf;
12492 	OSNumber *statusCode;
12493 	uint64_t pmStatusCode = 0;
12494 	uint32_t phaseData = 0;
12495 	uint32_t phaseDetail = 0;
12496 	bool efiFailure = false;
12497 
12498 	OSSharedPtr<OSObject> statusCodeProp = copyProperty(kIOPMSleepWakeFailureCodeKey);
12499 	statusCode = OSDynamicCast(OSNumber, statusCodeProp.get());
12500 	if (statusCode) {
12501 		pmStatusCode = statusCode->unsigned64BitValue();
12502 		phaseData = pmStatusCode & 0xFFFFFFFF;
12503 		phaseDetail = (pmStatusCode >> 32) & 0xFFFFFFFF;
12504 		if ((phaseData & 0xFF) == kIOPMTracePointSystemSleep) {
12505 			LOG("Sleep Wake failure in EFI\n");
12506 			efiFailure = true;
12507 			failureStr[0] = 0;
12508 			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);
12509 			len = (typeof(len))strnlen(failureStr, sizeof(failureStr));
12510 		}
12511 	}
12512 
12513 	if (!efiFailure) {
12514 		if (PEReadNVRAMProperty(kIOSleepWakeFailurePanic, NULL, &len)) {
12515 			swd_flags |= SWD_BOOT_BY_SW_WDOG;
12516 			PERemoveNVRAMProperty(kIOSleepWakeFailurePanic);
12517 			// dump panic will handle saving nvram data
12518 			return;
12519 		}
12520 
12521 		/* Keeping this around for capturing data during power
12522 		 * button press */
12523 
12524 		if (!PEReadNVRAMProperty(kIOSleepWakeFailureString, NULL, &len)) {
12525 			DLOG("No sleep wake failure string\n");
12526 			return;
12527 		}
12528 		if (len == 0) {
12529 			DLOG("Ignoring zero byte SleepWake failure string\n");
12530 			goto exit;
12531 		}
12532 
12533 		// if PMStatus code is zero, delete stackshot and return
12534 		if (statusCode) {
12535 			if (((pmStatusCode & 0xFFFFFFFF) & 0xFF) == 0) {
12536 				// there was no sleep wake failure
12537 				// this can happen if delete stackshot was called
12538 				// before take stackshot completed. Let us delete any
12539 				// sleep wake failure data in nvram
12540 				DLOG("Deleting stackshot on successful wake\n");
12541 				deleteStackshot();
12542 				return;
12543 			}
12544 		}
12545 
12546 		if (len > sizeof(failureStr)) {
12547 			len = sizeof(failureStr);
12548 		}
12549 		failureStr[0] = 0;
12550 		PEReadNVRAMProperty(kIOSleepWakeFailureString, failureStr, &len);
12551 	}
12552 	if (failureStr[0] != 0) {
12553 		error = sleepWakeDebugSaveFile(kSleepWakeFailureStringFile, failureStr, len);
12554 		if (error) {
12555 			DLOG("Failed to save SleepWake failure string to file. error:%d\n", error);
12556 		} else {
12557 			DLOG("Saved SleepWake failure string to file.\n");
12558 		}
12559 	}
12560 
12561 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12562 		goto exit;
12563 	}
12564 
12565 	if (swd_buffer) {
12566 		unsigned int len = 0;
12567 		errno_t error;
12568 		char nvram_var_name_buffer[20];
12569 		unsigned int concat_len = 0;
12570 		swd_hdr      *hdr = NULL;
12571 
12572 
12573 		hdr = (swd_hdr *)swd_buffer;
12574 		outbuf = (char *)hdr + hdr->spindump_offset;
12575 		OSBoundedArrayRef<char> boundedOutBuf(outbuf, hdr->alloc_size - hdr->spindump_offset);
12576 
12577 		for (int i = 0; i < 8; i++) {
12578 			snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12579 			if (!PEReadNVRAMProperty(nvram_var_name_buffer, NULL, &len)) {
12580 				LOG("No SleepWake blob to read beyond chunk %d\n", i);
12581 				break;
12582 			}
12583 			if (PEReadNVRAMProperty(nvram_var_name_buffer, boundedOutBuf.slice(concat_len, len).data(), &len) == FALSE) {
12584 				PERemoveNVRAMProperty(nvram_var_name_buffer);
12585 				LOG("Could not read the property :-(\n");
12586 				break;
12587 			}
12588 			PERemoveNVRAMProperty(nvram_var_name_buffer);
12589 			concat_len += len;
12590 		}
12591 		LOG("Concatenated length for the SWD blob %d\n", concat_len);
12592 
12593 		if (concat_len) {
12594 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, concat_len);
12595 			if (error) {
12596 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12597 			} else {
12598 				LOG("Saved SleepWake zipped data to file.\n");
12599 			}
12600 		} else {
12601 			// There is a sleep wake failure string but no stackshot
12602 			// Write a placeholder stacks file so that swd runs
12603 			snprintf(outbuf, 20, "%s", "No stackshot data\n");
12604 			error = sleepWakeDebugSaveFile(kSleepWakeStacksFilename, outbuf, 20);
12605 			if (error) {
12606 				LOG("Failed to save SleepWake zipped data to file. error:%d\n", error);
12607 			} else {
12608 				LOG("Saved SleepWake zipped data to file.\n");
12609 			}
12610 		}
12611 	} else {
12612 		LOG("No buffer allocated to save failure stackshot\n");
12613 	}
12614 
12615 
12616 	gRootDomain->swd_lock = 0;
12617 exit:
12618 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12619 	return;
12620 }
12621 
12622 
12623 void
12624 IOPMrootDomain::getFailureData(thread_t *thread, char *failureStr, size_t strLen)
12625 {
12626 	OSSharedPtr<IORegistryIterator>    iter;
12627 	OSSharedPtr<const OSSymbol>        kextName = NULL;
12628 	IORegistryEntry *       entry;
12629 	IOService *             node;
12630 	bool                    nodeFound = false;
12631 
12632 	const void *            callMethod = NULL;
12633 	const char *            objectName = NULL;
12634 	const char *            phaseString = NULL;
12635 	const char *            phaseDescription = NULL;
12636 	uint64_t                delta;
12637 
12638 	IOPMServiceInterestNotifier *notifier = OSDynamicCast(IOPMServiceInterestNotifier, notifierObject.get());
12639 	uint32_t tracePhase = pmTracer->getTracePhase();
12640 
12641 	*thread = NULL;
12642 
12643 	delta = get_watchdog_elapsed_time();
12644 	if ((tracePhase < kIOPMTracePointSystemSleep) || (tracePhase == kIOPMTracePointDarkWakeEntry)) {
12645 		snprintf(failureStr, strLen, "Sleep transition timed out after %qd seconds", delta);
12646 	} else {
12647 		snprintf(failureStr, strLen, "Wake transition timed out after %qd seconds", delta);
12648 	}
12649 	tracePhase2String(tracePhase, &phaseString, &phaseDescription);
12650 
12651 	if (notifierThread) {
12652 		if (notifier && (notifier->identifier)) {
12653 			objectName = notifier->identifier->getCStringNoCopy();
12654 		}
12655 		*thread = notifierThread;
12656 	} else {
12657 		iter = IORegistryIterator::iterateOver(
12658 			getPMRootDomain(), gIOPowerPlane, kIORegistryIterateRecursively);
12659 
12660 		if (iter) {
12661 			while ((entry = iter->getNextObject())) {
12662 				node = OSDynamicCast(IOService, entry);
12663 				if (!node) {
12664 					continue;
12665 				}
12666 				if (OSDynamicCast(IOPowerConnection, node)) {
12667 					continue;
12668 				}
12669 
12670 				if (node->getBlockingDriverCall(thread, &callMethod)) {
12671 					nodeFound = true;
12672 					break;
12673 				}
12674 			}
12675 		}
12676 		if (nodeFound) {
12677 			kextName = copyKextIdentifierWithAddress((vm_address_t) callMethod);
12678 			if (kextName) {
12679 				objectName = kextName->getCStringNoCopy();
12680 			}
12681 		}
12682 	}
12683 	if (phaseDescription) {
12684 		strlcat(failureStr, " while ", strLen);
12685 		strlcat(failureStr, phaseDescription, strLen);
12686 		strlcat(failureStr, ".", strLen);
12687 	}
12688 	if (objectName) {
12689 		strlcat(failureStr, " Suspected bundle: ", strLen);
12690 		strlcat(failureStr, objectName, strLen);
12691 		strlcat(failureStr, ".", strLen);
12692 	}
12693 	if (*thread) {
12694 		char threadName[40];
12695 		snprintf(threadName, sizeof(threadName), " Thread 0x%llx.", thread_tid(*thread));
12696 		strlcat(failureStr, threadName, strLen);
12697 	}
12698 
12699 	DLOG("%s\n", failureStr);
12700 }
12701 
12702 struct swd_stackshot_compressed_data {
12703 	z_output_func   zoutput;
12704 	size_t                  zipped;
12705 	uint64_t                totalbytes;
12706 	uint64_t                lastpercent;
12707 	IOReturn                error;
12708 	unsigned                outremain;
12709 	unsigned                outlen;
12710 	unsigned                writes;
12711 	Bytef *                 outbuf;
12712 };
12713 struct swd_stackshot_compressed_data swd_zip_var = { };
12714 
12715 static void *
12716 swd_zs_alloc(void *__unused ref, u_int items, u_int size)
12717 {
12718 	void *result;
12719 	LOG("Alloc in zipping %d items of size %d\n", items, size);
12720 
12721 	result = (void *)(swd_zs_zmem + swd_zs_zoffset);
12722 	swd_zs_zoffset += ~31L & (31 + (items * size)); // 32b align for vector crc
12723 	LOG("Offset %zu\n", swd_zs_zoffset);
12724 	return result;
12725 }
12726 
12727 static int
12728 swd_zinput(z_streamp strm, Bytef *buf, unsigned size)
12729 {
12730 	unsigned len;
12731 
12732 	len = strm->avail_in;
12733 
12734 	if (len > size) {
12735 		len = size;
12736 	}
12737 	if (len == 0) {
12738 		return 0;
12739 	}
12740 
12741 	if (strm->next_in != (Bytef *) strm) {
12742 		memcpy(buf, strm->next_in, len);
12743 	} else {
12744 		bzero(buf, len);
12745 	}
12746 
12747 	strm->adler = z_crc32(strm->adler, buf, len);
12748 
12749 	strm->avail_in -= len;
12750 	strm->next_in  += len;
12751 	strm->total_in += len;
12752 
12753 	return (int)len;
12754 }
12755 
12756 static int
12757 swd_zoutput(z_streamp strm, Bytef *buf, unsigned len)
12758 {
12759 	unsigned int i = 0;
12760 	// if outlen > max size don't add to the buffer
12761 	assert(buf != NULL);
12762 	if (strm && buf) {
12763 		if (swd_zip_var.outlen + len > SWD_COMPRESSED_BUFSIZE) {
12764 			LOG("No space to GZIP... not writing to NVRAM\n");
12765 			return len;
12766 		}
12767 	}
12768 	for (i = 0; i < len; i++) {
12769 		*(swd_zip_var.outbuf + swd_zip_var.outlen + i) = *(buf + i);
12770 	}
12771 	swd_zip_var.outlen += len;
12772 	return len;
12773 }
12774 
12775 static void
12776 swd_zs_free(void * __unused ref, void * __unused ptr)
12777 {
12778 }
12779 
12780 static int
12781 swd_compress(char *inPtr, char *outPtr, size_t numBytes)
12782 {
12783 	int wbits = 12;
12784 	int memlevel = 3;
12785 
12786 	if (((unsigned int) numBytes) != numBytes) {
12787 		return 0;
12788 	}
12789 
12790 	if (!swd_zs.zalloc) {
12791 		swd_zs.zalloc = swd_zs_alloc;
12792 		swd_zs.zfree = swd_zs_free;
12793 		if (deflateInit2(&swd_zs, Z_BEST_SPEED, Z_DEFLATED, wbits + 16, memlevel, Z_DEFAULT_STRATEGY)) {
12794 			// allocation failed
12795 			bzero(&swd_zs, sizeof(swd_zs));
12796 			// swd_zs_zoffset = 0;
12797 		} else {
12798 			LOG("PMRD inited the zlib allocation routines\n");
12799 		}
12800 	}
12801 
12802 	swd_zip_var.zipped = 0;
12803 	swd_zip_var.totalbytes = 0; // should this be the max that we have?
12804 	swd_zip_var.lastpercent = 0;
12805 	swd_zip_var.error = kIOReturnSuccess;
12806 	swd_zip_var.outremain = 0;
12807 	swd_zip_var.outlen = 0;
12808 	swd_zip_var.writes = 0;
12809 	swd_zip_var.outbuf = (Bytef *)outPtr;
12810 
12811 	swd_zip_var.totalbytes = numBytes;
12812 
12813 	swd_zs.avail_in = 0;
12814 	swd_zs.next_in = NULL;
12815 	swd_zs.avail_out = 0;
12816 	swd_zs.next_out = NULL;
12817 
12818 	deflateResetWithIO(&swd_zs, swd_zinput, swd_zoutput);
12819 
12820 	z_stream *zs;
12821 	int zr;
12822 	zs = &swd_zs;
12823 
12824 	while (swd_zip_var.error >= 0) {
12825 		if (!zs->avail_in) {
12826 			zs->next_in = (unsigned char *)inPtr ? (Bytef *)inPtr : (Bytef *)zs; /* zero marker? */
12827 			zs->avail_in = (unsigned int) numBytes;
12828 		}
12829 		if (!zs->avail_out) {
12830 			zs->next_out = (Bytef *)zs;
12831 			zs->avail_out = UINT32_MAX;
12832 		}
12833 		zr = deflate(zs, Z_NO_FLUSH);
12834 		if (Z_STREAM_END == zr) {
12835 			break;
12836 		}
12837 		if (zr != Z_OK) {
12838 			LOG("ZERR %d\n", zr);
12839 			swd_zip_var.error = zr;
12840 		} else {
12841 			if (zs->total_in == numBytes) {
12842 				break;
12843 			}
12844 		}
12845 	}
12846 
12847 	//now flush the stream
12848 	while (swd_zip_var.error >= 0) {
12849 		if (!zs->avail_out) {
12850 			zs->next_out = (Bytef *)zs;
12851 			zs->avail_out = UINT32_MAX;
12852 		}
12853 		zr = deflate(zs, Z_FINISH);
12854 		if (Z_STREAM_END == zr) {
12855 			break;
12856 		}
12857 		if (zr != Z_OK) {
12858 			LOG("ZERR %d\n", zr);
12859 			swd_zip_var.error = zr;
12860 		} else {
12861 			if (zs->total_in == numBytes) {
12862 				LOG("Total output size %d\n", swd_zip_var.outlen);
12863 				break;
12864 			}
12865 		}
12866 	}
12867 
12868 	return swd_zip_var.outlen;
12869 }
12870 
12871 void
12872 IOPMrootDomain::deleteStackshot()
12873 {
12874 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12875 		// takeStackshot hasn't completed
12876 		return;
12877 	}
12878 	LOG("Deleting any sleepwake failure data in nvram\n");
12879 
12880 	PERemoveNVRAMProperty(kIOSleepWakeFailureString);
12881 	char nvram_var_name_buf[20];
12882 	for (int i = 0; i < 8; i++) {
12883 		snprintf(nvram_var_name_buf, sizeof(nvram_var_name_buf), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, i + 1);
12884 		if (PERemoveNVRAMProperty(nvram_var_name_buf) == false) {
12885 			LOG("Removing %s returned false\n", nvram_var_name_buf);
12886 		}
12887 	}
12888 	// force NVRAM sync
12889 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
12890 		DLOG("Failed to force nvram sync\n");
12891 	}
12892 	gRootDomain->swd_lock = 0;
12893 }
12894 
12895 void
12896 IOPMrootDomain::takeStackshot(bool wdogTrigger)
12897 {
12898 	swd_hdr *                hdr = NULL;
12899 	int                      cnt = 0;
12900 	int                      max_cnt;
12901 	pid_t                    pid = 0;
12902 	kern_return_t            kr = KERN_SUCCESS;
12903 	uint64_t                 flags;
12904 
12905 	char *                   dstAddr;
12906 	uint32_t                 size;
12907 	uint32_t                 bytesRemaining;
12908 	unsigned                 bytesWritten = 0;
12909 
12910 	char                     failureStr[512];
12911 	thread_t                 thread = NULL;
12912 	const char *             swfPanic = "swfPanic";
12913 
12914 	uint32_t                 bufSize;
12915 	int                      success = 0;
12916 
12917 #if defined(__i386__) || defined(__x86_64__)
12918 	const bool               concise = false;
12919 #else
12920 	const bool               concise = true;
12921 #endif
12922 
12923 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
12924 		return;
12925 	}
12926 
12927 	failureStr[0] = 0;
12928 	if ((kIOSleepWakeWdogOff & gIOKitDebug) || systemBooting || systemShutdown || gWillShutdown) {
12929 		return;
12930 	}
12931 
12932 	if (wdogTrigger) {
12933 		getFailureData(&thread, failureStr, sizeof(failureStr));
12934 
12935 		if (concise || (PEGetCoprocessorVersion() >= kCoprocessorVersion2)) {
12936 			goto skip_stackshot;
12937 		}
12938 	} else {
12939 		AbsoluteTime now;
12940 		uint64_t nsec;
12941 		clock_get_uptime(&now);
12942 		SUB_ABSOLUTETIME(&now, &gIOLastWakeAbsTime);
12943 		absolutetime_to_nanoseconds(now, &nsec);
12944 		snprintf(failureStr, sizeof(failureStr), "Power button pressed during wake transition after %u ms.\n", ((int)((nsec) / NSEC_PER_MSEC)));
12945 	}
12946 
12947 	if (swd_buffer == NULL) {
12948 		sleepWakeDebugMemAlloc();
12949 		if (swd_buffer == NULL) {
12950 			return;
12951 		}
12952 	}
12953 	hdr = (swd_hdr *)swd_buffer;
12954 	bufSize = hdr->alloc_size;
12955 
12956 	dstAddr = (char*)hdr + hdr->spindump_offset;
12957 	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;
12958 
12959 	/* If not wdogTrigger only take kernel tasks stackshot
12960 	 */
12961 	if (wdogTrigger) {
12962 		pid = -1;
12963 		max_cnt = 3;
12964 	} else {
12965 		pid = 0;
12966 		max_cnt = 2;
12967 	}
12968 
12969 	/* Attempt to take stackshot with all ACTIVE_KERNEL_THREADS
12970 	 * If we run out of space, take stackshot with only kernel task
12971 	 */
12972 	while (success == 0 && cnt < max_cnt) {
12973 		bytesRemaining = bufSize - hdr->spindump_offset;
12974 		cnt++;
12975 		DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
12976 
12977 		size = bytesRemaining;
12978 		kr = stack_snapshot_from_kernel(pid, dstAddr, size, flags, 0, 0, &bytesWritten);
12979 		DLOG("stack_snapshot_from_kernel returned 0x%x. pid: %d bufsize:0x%x flags:0x%llx bytesWritten: %d\n",
12980 		    kr, pid, size, flags, bytesWritten);
12981 		if (kr == KERN_INSUFFICIENT_BUFFER_SIZE) {
12982 			if (pid == -1) {
12983 				pid = 0;
12984 			} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
12985 				flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
12986 			} else {
12987 				LOG("Insufficient buffer size for only kernel task\n");
12988 				break;
12989 			}
12990 		}
12991 		if (kr == KERN_SUCCESS) {
12992 			if (bytesWritten == 0) {
12993 				MSG("Failed to get stackshot(0x%x) bufsize:0x%x flags:0x%llx\n", kr, size, flags);
12994 				continue;
12995 			}
12996 			bytesRemaining -= bytesWritten;
12997 			hdr->spindump_size = (bufSize - bytesRemaining - hdr->spindump_offset);
12998 
12999 			memset(hdr->reason, 0x20, sizeof(hdr->reason));
13000 
13001 			// Compress stackshot and save to NVRAM
13002 			{
13003 				char *outbuf = (char *)swd_compressed_buffer;
13004 				int outlen = 0;
13005 				int num_chunks = 0;
13006 				int max_chunks = 0;
13007 				int leftover = 0;
13008 				char nvram_var_name_buffer[20];
13009 
13010 				outlen = swd_compress((char*)hdr + hdr->spindump_offset, outbuf, bytesWritten);
13011 
13012 				if (outlen) {
13013 					max_chunks = outlen / (2096 - 200);
13014 					leftover = outlen % (2096 - 200);
13015 
13016 					if (max_chunks < 8) {
13017 						for (num_chunks = 0; num_chunks < max_chunks; num_chunks++) {
13018 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
13019 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), (2096 - 200)) == FALSE) {
13020 								LOG("Failed to update NVRAM %d\n", num_chunks);
13021 								break;
13022 							}
13023 						}
13024 						if (leftover) {
13025 							snprintf(nvram_var_name_buffer, sizeof(nvram_var_name_buffer), "%s%02d", SWD_STACKSHOT_VAR_PREFIX, num_chunks + 1);
13026 							if (PEWriteNVRAMPropertyWithCopy(nvram_var_name_buffer, (outbuf + (num_chunks * (2096 - 200))), leftover) == FALSE) {
13027 								LOG("Failed to update NVRAM with leftovers\n");
13028 							}
13029 						}
13030 						success = 1;
13031 						LOG("Successfully saved stackshot to NVRAM\n");
13032 					} else {
13033 						if (pid == -1) {
13034 							LOG("Compressed failure stackshot is too large. size=%d bytes\n", outlen);
13035 							pid = 0;
13036 						} else if (flags & STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL) {
13037 							LOG("Compressed failure stackshot of kernel+dexts is too large size=%d bytes\n", outlen);
13038 							flags = flags & ~STACKSHOT_INCLUDE_DRIVER_THREADS_IN_KERNEL;
13039 						} else {
13040 							LOG("Compressed failure stackshot of only kernel is too large size=%d bytes\n", outlen);
13041 							break;
13042 						}
13043 					}
13044 				}
13045 			}
13046 		}
13047 	}
13048 
13049 	if (failureStr[0]) {
13050 		// append sleep-wake failure code
13051 		char traceCode[80];
13052 		snprintf(traceCode, sizeof(traceCode), "\nFailure code:: 0x%08x %08x\n",
13053 		    pmTracer->getTraceData(), pmTracer->getTracePhase());
13054 		strlcat(failureStr, traceCode, sizeof(failureStr));
13055 		if (PEWriteNVRAMProperty(kIOSleepWakeFailureString, failureStr, (unsigned int) strnlen(failureStr, sizeof(failureStr))) == false) {
13056 			DLOG("Failed to write SleepWake failure string\n");
13057 		}
13058 	}
13059 
13060 	// force NVRAM sync
13061 	if (PEWriteNVRAMProperty(kIONVRAMSyncNowPropertyKey, kIONVRAMSyncNowPropertyKey, (unsigned int) strlen(kIONVRAMSyncNowPropertyKey)) == false) {
13062 		DLOG("Failed to force nvram sync\n");
13063 	}
13064 
13065 skip_stackshot:
13066 	if (wdogTrigger) {
13067 		if (PEGetCoprocessorVersion() < kCoprocessorVersion2) {
13068 			if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
13069 				// If current boot is due to this watch dog trigger restart in previous boot,
13070 				// then don't trigger again until at least 1 successful sleep & wake.
13071 				if (!(sleepCnt && (displayWakeCnt || darkWakeCnt))) {
13072 					LOG("Shutting down due to repeated Sleep/Wake failures\n");
13073 					updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
13074 					PEHaltRestart(kPEHaltCPU);
13075 					return;
13076 				}
13077 			}
13078 			if (gSwdPanic == 0) {
13079 				LOG("Calling panic prevented by swd_panic boot-args. Calling restart");
13080 				updateTasksSuspend(kTasksSuspendSuspended, kTasksSuspendNoChange);
13081 				PEHaltRestart(kPERestartCPU);
13082 			}
13083 		}
13084 		if (!concise && (PEWriteNVRAMProperty(kIOSleepWakeFailurePanic, swfPanic, (unsigned int) strlen(swfPanic)) == false)) {
13085 			DLOG("Failed to write SleepWake failure panic key\n");
13086 		}
13087 #if defined(__x86_64__)
13088 		if (thread) {
13089 			panic_with_thread_context(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, thread, "%s", failureStr);
13090 		} else
13091 #endif /* defined(__x86_64__) */
13092 		{
13093 			panic_with_options(0, NULL, DEBUGGER_OPTION_ATTEMPTCOREDUMPANDREBOOT, "%s", failureStr);
13094 		}
13095 	} else {
13096 		gRootDomain->swd_lock = 0;
13097 		return;
13098 	}
13099 }
13100 
13101 void
13102 IOPMrootDomain::sleepWakeDebugMemAlloc()
13103 {
13104 	vm_size_t    size = SWD_STACKSHOT_SIZE + SWD_COMPRESSED_BUFSIZE + SWD_ZLIB_BUFSIZE;
13105 
13106 	swd_hdr      *hdr = NULL;
13107 	void         *bufPtr = NULL;
13108 
13109 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
13110 
13111 
13112 	if (kIOSleepWakeWdogOff & gIOKitDebug) {
13113 		return;
13114 	}
13115 
13116 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
13117 		return;
13118 	}
13119 
13120 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
13121 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
13122 		size);
13123 	if (memDesc == NULL) {
13124 		DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
13125 		goto exit;
13126 	}
13127 
13128 	bufPtr = memDesc->getBytesNoCopy();
13129 
13130 	// Carve out memory for zlib routines
13131 	swd_zs_zmem = (vm_offset_t)bufPtr;
13132 	bufPtr = (char *)bufPtr + SWD_ZLIB_BUFSIZE;
13133 
13134 	// Carve out memory for compressed stackshots
13135 	swd_compressed_buffer = bufPtr;
13136 	bufPtr = (char *)bufPtr + SWD_COMPRESSED_BUFSIZE;
13137 
13138 	// Remaining is used for holding stackshot
13139 	hdr = (swd_hdr *)bufPtr;
13140 	memset(hdr, 0, sizeof(swd_hdr));
13141 
13142 	hdr->signature = SWD_HDR_SIGNATURE;
13143 	hdr->alloc_size = SWD_STACKSHOT_SIZE;
13144 
13145 	hdr->spindump_offset = sizeof(swd_hdr);
13146 	swd_buffer = (void *)hdr;
13147 	swd_memDesc = os::move(memDesc);
13148 	DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
13149 
13150 exit:
13151 	gRootDomain->swd_lock = 0;
13152 }
13153 
13154 void
13155 IOPMrootDomain::sleepWakeDebugSpinDumpMemAlloc()
13156 {
13157 #if UNUSED
13158 	vm_size_t    size = SWD_SPINDUMP_SIZE;
13159 
13160 	swd_hdr      *hdr = NULL;
13161 
13162 	OSSharedPtr<IOBufferMemoryDescriptor>  memDesc;
13163 
13164 	if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock)) {
13165 		return;
13166 	}
13167 
13168 	memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(
13169 		kernel_task, kIODirectionIn | kIOMemoryMapperNone,
13170 		SWD_SPINDUMP_SIZE);
13171 
13172 	if (memDesc == NULL) {
13173 		DLOG("Failed to allocate Memory descriptor for sleepWake debug spindump\n");
13174 		goto exit;
13175 	}
13176 
13177 
13178 	hdr = (swd_hdr *)memDesc->getBytesNoCopy();
13179 	memset(hdr, 0, sizeof(swd_hdr));
13180 
13181 	hdr->signature = SWD_HDR_SIGNATURE;
13182 	hdr->alloc_size = size;
13183 
13184 	hdr->spindump_offset = sizeof(swd_hdr);
13185 	swd_spindump_buffer = (void *)hdr;
13186 	swd_spindump_memDesc = os::move(memDesc);
13187 
13188 exit:
13189 	gRootDomain->swd_lock = 0;
13190 #endif /* UNUSED */
13191 }
13192 
13193 void
13194 IOPMrootDomain::sleepWakeDebugEnableWdog()
13195 {
13196 }
13197 
13198 bool
13199 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
13200 {
13201 	return !systemBooting && !systemShutdown && !gWillShutdown;
13202 }
13203 
13204 void
13205 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
13206 {
13207 	swd_hdr *hdr = NULL;
13208 	errno_t error = EIO;
13209 
13210 	if (swd_spindump_buffer && gSpinDumpBufferFull) {
13211 		hdr = (swd_hdr *)swd_spindump_buffer;
13212 
13213 		error = sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayStacks.dump",
13214 		    (char*)hdr + hdr->spindump_offset, hdr->spindump_size);
13215 
13216 		if (error) {
13217 			return;
13218 		}
13219 
13220 		sleepWakeDebugSaveFile("/var/tmp/SleepWakeDelayLog.dump",
13221 		    (char*)hdr + offsetof(swd_hdr, UUID),
13222 		    sizeof(swd_hdr) - offsetof(swd_hdr, UUID));
13223 
13224 		gSpinDumpBufferFull = false;
13225 	}
13226 }
13227 
13228 errno_t
13229 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
13230 {
13231 	struct vnode         *vp = NULL;
13232 	vfs_context_t        ctx = vfs_context_create(vfs_context_current());
13233 	kauth_cred_t         cred = vfs_context_ucred(ctx);
13234 	struct vnode_attr    va;
13235 	errno_t      error = EIO;
13236 
13237 	if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
13238 	    S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0) {
13239 		LOG("Failed to open the file %s\n", name);
13240 		swd_flags |= SWD_FILEOP_ERROR;
13241 		goto exit;
13242 	}
13243 	VATTR_INIT(&va);
13244 	VATTR_WANTED(&va, va_nlink);
13245 	/* Don't dump to non-regular files or files with links. */
13246 	if (vp->v_type != VREG ||
13247 	    vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
13248 		LOG("Bailing as this is not a regular file\n");
13249 		swd_flags |= SWD_FILEOP_ERROR;
13250 		goto exit;
13251 	}
13252 	VATTR_INIT(&va);
13253 	VATTR_SET(&va, va_data_size, 0);
13254 	vnode_setattr(vp, &va, ctx);
13255 
13256 
13257 	if (buf != NULL) {
13258 		error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
13259 		    UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, vfs_context_proc(ctx));
13260 		if (error != 0) {
13261 			LOG("Failed to save sleep wake log. err 0x%x\n", error);
13262 			swd_flags |= SWD_FILEOP_ERROR;
13263 		} else {
13264 			DLOG("Saved %d bytes to file %s\n", len, name);
13265 		}
13266 	}
13267 
13268 exit:
13269 	if (vp) {
13270 		vnode_close(vp, FWRITE, ctx);
13271 	}
13272 	if (ctx) {
13273 		vfs_context_rele(ctx);
13274 	}
13275 
13276 	return error;
13277 }
13278 
13279 #else /* defined(__i386__) || defined(__x86_64__) */
13280 
13281 void
13282 IOPMrootDomain::sleepWakeDebugTrig(bool restart)
13283 {
13284 	if (restart) {
13285 		if (gSwdPanic == 0) {
13286 			return;
13287 		}
13288 		panic("Sleep/Wake hang detected");
13289 		return;
13290 	}
13291 }
13292 
13293 void
13294 IOPMrootDomain::takeStackshot(bool restart)
13295 {
13296 #pragma unused(restart)
13297 }
13298 
13299 void
13300 IOPMrootDomain::deleteStackshot()
13301 {
13302 }
13303 
13304 void
13305 IOPMrootDomain::sleepWakeDebugMemAlloc()
13306 {
13307 }
13308 
13309 void
13310 IOPMrootDomain::saveFailureData2File()
13311 {
13312 }
13313 
13314 void
13315 IOPMrootDomain::sleepWakeDebugEnableWdog()
13316 {
13317 }
13318 
13319 bool
13320 IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
13321 {
13322 	return false;
13323 }
13324 
13325 void
13326 IOPMrootDomain::sleepWakeDebugSaveSpinDumpFile()
13327 {
13328 }
13329 
13330 errno_t
13331 IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
13332 {
13333 	return 0;
13334 }
13335 
13336 #endif /* defined(__i386__) || defined(__x86_64__) */
13337 
13338