2 * Copyright (c) 2004-2008 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
34 - PMRootDomain calls IOHibernateSystemSleep() before system sleep
35 (devices awake, normal execution context)
36 - IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level,
37 grabs its extents and searches for a polling driver willing to work with that IOMedia.
38 The BSD code makes an ioctl to the storage driver to get the partition base offset to
39 the disk, and other ioctls to get the transfer constraints
40 If successful, the file is written to make sure its initially not bootable (in case of
41 later failure) and nvram set to point to the first block of the file. (Has to be done
42 here so blocking is possible in nvram support).
43 hibernate_setup() in osfmk is called to allocate page bitmaps for all dram, and
44 page out any pages it wants to (currently zero, but probably some percentage of memory).
45 Its assumed just allocating pages will cause the VM system to naturally select the best
46 pages for eviction. It also copies processor flags needed for the restore path and sets
47 a flag in the boot processor proc info.
48 gIOHibernateState = kIOHibernateStateHibernating.
49 - Regular sleep progresses - some drivers may inspect the root domain property
50 kIOHibernateStateKey to modify behavior. The platform driver saves state to memory
51 as usual but leaves motherboard I/O on.
52 - Eventually the platform calls ml_ppc_sleep() in the shutdown context on the last cpu,
53 at which point memory is ready to be saved. mapping_hibernate_flush() is called to get
54 all ppc RC bits out of the hash table and caches into the mapping structures.
55 - hibernate_write_image() is called (still in shutdown context, no blocking or preemption).
56 hibernate_page_list_setall() is called to get a bitmap of dram pages that need to be saved.
57 All pages are assumed to be saved (as part of the wired image) unless explicitly subtracted
58 by hibernate_page_list_setall(), avoiding having to find arch dependent low level bits.
59 The image header and block list are written. The header includes the second file extent so
60 only the header block is needed to read the file, regardless of filesystem.
61 The kernel section "__HIB" is written uncompressed to the image. This section of code and data
62 (only) is used to decompress the image during wake/boot.
63 Some additional pages are removed from the bitmaps - the buffers used for hibernation.
64 The bitmaps are written to the image.
65 More areas are removed from the bitmaps (after they have been written to the image) - the
66 section "__HIB" pages and interrupt stack.
67 Each wired page is compressed and written and then each non-wired page. Compression and
68 disk writes are in parallel.
69 The image header is written to the start of the file and the polling driver closed.
70 The machine powers down (or sleeps).
74 - BootX sees the boot-image nvram variable containing the device and block number of the image,
75 reads the header and if the signature is correct proceeds. The boot-image variable is cleared.
76 - BootX reads the portion of the image used for wired pages, to memory. Its assumed this will fit
77 in the OF memory environment, and the image is decrypted. There is no decompression in BootX,
78 that is in the kernel's __HIB section.
79 - BootX copies the "__HIB" section to its correct position in memory, quiesces and calls its entry
80 hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off,
81 only code & data in that section is safe to call since all the other wired pages are still
82 compressed in the image.
83 - hibernate_kernel_entrypoint() removes pages occupied by the raw image from the page bitmaps.
84 It uses the bitmaps to work out which pages can be uncompressed from the image to their final
85 location directly, and copies those that can't to interim free pages. When the image has been
86 completed, the copies are uncompressed, overwriting the wired image pages.
87 hibernate_restore_phys_page() (in osfmk since its arch dependent, but part of the "__HIB" section)
88 is used to get pages into place for 64bit.
89 - the reset vector is called (at least on ppc), the kernel proceeds on a normal wake, with some
90 changes conditional on the per proc flag - before VM is turned on the boot cpu, all mappings
91 are removed from the software strutures, and the hash table is reinitialized.
92 - After the platform CPU init code is called, hibernate_machine_init() is called to restore the rest
93 of memory, using the polled mode driver, before other threads can run or any devices are turned on.
94 This reduces the memory usage for BootX and allows decompression in parallel with disk reads,
95 for the remaining non wired pages.
96 - The polling driver is closed down and regular wake proceeds. When the kernel calls iokit to wake
97 (normal execution context) hibernate_teardown() in osmfk is called to release any memory, the file
102 IOHibernateSystemSleep() finds a polled mode interface to the ATA controller via a property in the
103 registry, specifying an object of calls IOPolledInterface.
105 Before the system goes to sleep it searches from the IOMedia object (could be a filesystem or
106 partition) that the image is going to live, looking for polled interface properties. If it finds
107 one the IOMedia object is passed to a "probe" call for the interface to accept or reject. All the
108 interfaces found are kept in an ordered list.
110 There is an Open/Close pair of calls made to each of the interfaces at various stages since there are
111 few different contexts things happen in:
113 - there is an Open/Close (Preflight) made before any part of the system has slept (I/O is all
114 up and running) and after wake - this is safe to allocate memory and do anything. The device
115 ignores sleep requests from that point since its a waste of time if it goes to sleep and
116 immediately wakes back up for the image write.
118 - there is an Open/Close (BeforeSleep) pair made around the image write operations that happen
119 immediately before sleep. These can't block or allocate memory - the I/O system is asleep apart
120 from the low level bits (motherboard I/O etc). There is only one thread running. The close can be
121 used to flush and set the disk to sleep.
123 - there is an Open/Close (AfterSleep) pair made around the image read operations that happen
124 immediately after sleep. These can't block or allocate memory. This is happening after the platform
125 expert has woken the low level bits of the system, but most of the I/O system has not. There is only
128 For the actual I/O, all the ops are with respect to a single IOMemoryDescriptor that was passed
129 (prepared) to the Preflight Open() call. There is a read/write op, buffer offset to the IOMD for
130 the data, an offset to the disk and length (block aligned 64 bit numbers), and completion callback.
131 Each I/O is async but only one is ever outstanding. The polled interface has a checkForWork call
132 that is called for the hardware to check for events, and complete the I/O via the callback.
133 The hibernate path uses the same transfer constraints the regular cluster I/O path in BSD uses
137 #include <sys/systm.h>
139 #include <IOKit/IOWorkLoop.h>
140 #include <IOKit/IOCommandGate.h>
141 #include <IOKit/IOTimerEventSource.h>
142 #include <IOKit/IOPlatformExpert.h>
143 #include <IOKit/IOKitDebug.h>
144 #include <IOKit/IOTimeStamp.h>
145 #include <IOKit/pwr_mgt/RootDomain.h>
146 #include <IOKit/pwr_mgt/IOPMPrivate.h>
147 #include <IOKit/IOMessage.h>
148 #include <IOKit/IODeviceTreeSupport.h>
149 #include <IOKit/IOBSD.h>
150 #include "RootDomainUserClient.h"
151 #include <IOKit/pwr_mgt/IOPowerConnection.h>
152 #include "IOPMPowerStateQueue.h"
153 #include <IOKit/IOBufferMemoryDescriptor.h>
154 #include <IOKit/AppleKeyStoreInterface.h>
155 #include <crypto/aes.h>
158 #include <sys/conf.h>
159 #include <sys/stat.h>
160 #include <sys/fcntl.h> // (FWRITE, ...)
161 #include <sys/sysctl.h>
162 #include <sys/kdebug.h>
164 #include <IOKit/IOHibernatePrivate.h>
165 #include <IOKit/IOPolledInterface.h>
166 #include <IOKit/IONVRAM.h>
167 #include "IOHibernateInternal.h"
168 #include <libkern/WKdm.h>
169 #include "IOKitKernelInternal.h"
170 #include <pexpert/device_tree.h>
172 #include <machine/pal_routines.h>
173 #include <machine/pal_hibernate.h>
175 extern "C" addr64_t
kvtophys(vm_offset_t va
);
177 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 extern unsigned int save_kdebug_enable
;
180 extern uint32_t gIOHibernateState
;
181 uint32_t gIOHibernateMode
;
182 static char gIOHibernateBootSignature
[256+1];
183 static char gIOHibernateFilename
[MAXPATHLEN
+1];
184 static uint32_t gIOHibernateFreeRatio
= 0; // free page target (percent)
185 uint32_t gIOHibernateFreeTime
= 0*1000; // max time to spend freeing pages (ms)
187 static IODTNVRAM
* gIOOptionsEntry
;
188 static IORegistryEntry
* gIOChosenEntry
;
189 #if defined(__i386__) || defined(__x86_64__)
190 static const OSSymbol
* gIOCreateEFIDevicePathSymbol
;
191 static const OSSymbol
* gIOHibernateRTCVariablesKey
;
192 static const OSSymbol
* gIOHibernateBoot0082Key
;
193 static const OSSymbol
* gIOHibernateBootNextKey
;
194 static OSData
* gIOHibernateBoot0082Data
;
195 static OSData
* gIOHibernateBootNextData
;
196 static OSObject
* gIOHibernateBootNextSave
;
199 static IOPolledFileIOVars gFileVars
;
200 static IOHibernateVars gIOHibernateVars
;
201 static struct kern_direct_file_io_ref_t
* gIOHibernateFileRef
;
202 static hibernate_cryptvars_t gIOHibernateCryptWakeContext
;
203 static hibernate_graphics_t _hibernateGraphics
;
204 static hibernate_graphics_t
* gIOHibernateGraphicsInfo
= &_hibernateGraphics
;
206 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
208 enum { kXPRamAudioVolume
= 8 };
209 enum { kDefaultIOSize
= 128 * 1024 };
210 enum { kVideoMapSize
= 32 * 1024 * 1024 };
212 #ifndef kIOMediaPreferredBlockSizeKey
213 #define kIOMediaPreferredBlockSizeKey "Preferred Block Size"
216 #ifndef kIOBootPathKey
217 #define kIOBootPathKey "bootpath"
219 #ifndef kIOSelectedBootDeviceKey
220 #define kIOSelectedBootDeviceKey "boot-device"
224 enum { kIOHibernateMinPollersNeeded
= 2 };
226 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
228 // copy from phys addr to MD
231 IOMemoryDescriptorWriteFromPhysical(IOMemoryDescriptor
* md
,
232 IOByteCount offset
, addr64_t bytes
, IOByteCount length
)
234 addr64_t srcAddr
= bytes
;
235 IOByteCount remaining
;
237 remaining
= length
= min(length
, md
->getLength() - offset
);
238 while (remaining
) { // (process another target segment?)
242 dstAddr64
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
);
246 // Clip segment length to remaining
247 if (dstLen
> remaining
)
251 bcopy_phys(srcAddr
, dstAddr64
, dstLen
);
253 copypv(srcAddr
, dstAddr64
, dstLen
,
254 cppvPsnk
| cppvFsnk
| cppvNoRefSrc
| cppvNoModSnk
| cppvKmap
);
263 return remaining
? kIOReturnUnderrun
: kIOReturnSuccess
;
266 // copy from MD to phys addr
269 IOMemoryDescriptorReadToPhysical(IOMemoryDescriptor
* md
,
270 IOByteCount offset
, addr64_t bytes
, IOByteCount length
)
272 addr64_t dstAddr
= bytes
;
273 IOByteCount remaining
;
275 remaining
= length
= min(length
, md
->getLength() - offset
);
276 while (remaining
) { // (process another target segment?)
280 srcAddr64
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
);
284 // Clip segment length to remaining
285 if (dstLen
> remaining
)
289 bcopy_phys(srcAddr64
, dstAddr
, dstLen
);
291 copypv(srcAddr
, dstAddr64
, dstLen
,
292 cppvPsnk
| cppvFsnk
| cppvNoRefSrc
| cppvNoModSnk
| cppvKmap
);
301 return remaining
? kIOReturnUnderrun
: kIOReturnSuccess
;
304 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
307 hibernate_set_page_state(hibernate_page_list_t
* page_list
, hibernate_page_list_t
* page_list_wired
,
308 vm_offset_t ppnum
, vm_offset_t count
, uint32_t kind
)
313 case kIOHibernatePageStateUnwiredSave
:
315 for (; ppnum
< count
; ppnum
++)
317 hibernate_page_bitset(page_list
, FALSE
, ppnum
);
318 hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
);
321 case kIOHibernatePageStateWiredSave
:
323 for (; ppnum
< count
; ppnum
++)
325 hibernate_page_bitset(page_list
, FALSE
, ppnum
);
326 hibernate_page_bitset(page_list_wired
, FALSE
, ppnum
);
329 case kIOHibernatePageStateFree
:
331 for (; ppnum
< count
; ppnum
++)
333 hibernate_page_bitset(page_list
, TRUE
, ppnum
);
334 hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
);
338 panic("hibernate_set_page_state");
343 hibernate_page_list_iterate(hibernate_page_list_t
* list
, vm_offset_t
* pPage
)
345 uint32_t page
= *pPage
;
347 hibernate_bitmap_t
* bitmap
;
349 while ((bitmap
= hibernate_page_bitmap_pin(list
, &page
)))
351 count
= hibernate_page_bitmap_count(bitmap
, TRUE
, page
);
355 if (page
<= bitmap
->last_page
)
361 count
= hibernate_page_bitmap_count(bitmap
, FALSE
, page
);
368 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
371 IOHibernatePollerProbe(IOPolledFileIOVars
* vars
, IOService
* target
)
373 IOReturn err
= kIOReturnError
;
375 IOPolledInterface
* poller
;
377 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
379 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
380 err
= poller
->probe(target
);
383 HIBLOG("IOPolledInterface::probe[%d] 0x%x\n", idx
, err
);
392 IOHibernatePollerOpen(IOPolledFileIOVars
* vars
, uint32_t state
, IOMemoryDescriptor
* md
)
394 IOReturn err
= kIOReturnError
;
396 IOPolledInterface
* poller
;
398 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
400 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
401 err
= poller
->open(state
, md
);
404 HIBLOG("IOPolledInterface::open[%d] 0x%x\n", idx
, err
);
413 IOHibernatePollerClose(IOPolledFileIOVars
* vars
, uint32_t state
)
415 IOReturn err
= kIOReturnError
;
417 IOPolledInterface
* poller
;
420 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
423 err
= poller
->close(state
);
425 HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx
, err
);
432 IOHibernatePollerIOComplete(void * target
,
435 UInt64 actualByteCount
)
437 IOPolledFileIOVars
* vars
= (IOPolledFileIOVars
*) parameter
;
439 vars
->ioStatus
= status
;
443 IOHibernatePollerIO(IOPolledFileIOVars
* vars
,
444 uint32_t operation
, uint32_t bufferOffset
,
445 uint64_t deviceOffset
, uint64_t length
)
448 IOReturn err
= kIOReturnError
;
449 IOPolledInterface
* poller
;
450 IOPolledCompletion completion
;
452 completion
.target
= 0;
453 completion
.action
= &IOHibernatePollerIOComplete
;
454 completion
.parameter
= vars
;
458 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(0);
459 err
= poller
->startIO(operation
, bufferOffset
, deviceOffset
+ vars
->block0
, length
, completion
);
461 HIBLOG("IOPolledInterface::startIO[%d] 0x%x\n", 0, err
);
467 IOHibernatePollerIODone(IOPolledFileIOVars
* vars
, bool abortable
)
469 IOReturn err
= kIOReturnSuccess
;
471 IOPolledInterface
* poller
;
473 while (-1 == vars
->ioStatus
)
476 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
480 newErr
= poller
->checkForWork();
481 if ((newErr
== kIOReturnAborted
) && !abortable
)
482 newErr
= kIOReturnSuccess
;
483 if (kIOReturnSuccess
== err
)
488 if ((kIOReturnSuccess
== err
) && abortable
&& hibernate_should_abort())
490 err
= kIOReturnAborted
;
491 HIBLOG("IOPolledInterface::checkForWork sw abort\n");
496 HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx
, err
);
500 err
= vars
->ioStatus
;
501 if (kIOReturnSuccess
!= err
)
502 HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err
);
509 IOPolledInterface::checkAllForWork(void)
511 IOReturn err
= kIOReturnNotReady
;
513 IOPolledInterface
* poller
;
515 IOHibernateVars
* vars
= &gIOHibernateVars
;
517 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
)
521 (poller
= (IOPolledInterface
*) vars
->fileVars
->pollers
->getObject(idx
));
524 err
= poller
->checkForWork();
526 HIBLOG("IOPolledInterface::checkAllForWork[%d] 0x%x\n", idx
, err
);
532 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
534 struct _OpenFileContext
541 file_extent_callback(void * ref
, uint64_t start
, uint64_t length
)
543 _OpenFileContext
* ctx
= (_OpenFileContext
*) ref
;
544 IOPolledFileExtent extent
;
546 extent
.start
= start
;
547 extent
.length
= length
;
549 ctx
->extents
->appendBytes(&extent
, sizeof(extent
));
554 IOCopyMediaForDev(dev_t device
)
556 OSDictionary
* matching
;
559 IOService
* result
= 0;
561 matching
= IOService::serviceMatching("IOMedia");
566 num
= OSNumber::withNumber(major(device
), 32);
569 matching
->setObject(kIOBSDMajorKey
, num
);
571 num
= OSNumber::withNumber(minor(device
), 32);
574 matching
->setObject(kIOBSDMinorKey
, num
);
578 iter
= IOService::getMatchingServices(matching
);
581 result
= (IOService
*) iter
->getNextObject();
593 IOPolledFileOpen( const char * filename
, IOBufferMemoryDescriptor
* ioBuffer
,
594 IOPolledFileIOVars
** fileVars
, OSData
** fileExtents
,
595 OSData
** imagePath
, uint8_t * volumeCryptKey
)
597 IOReturn err
= kIOReturnError
;
598 IOPolledFileIOVars
* vars
;
599 _OpenFileContext ctx
;
600 OSData
* extentsData
;
602 IOService
* part
= 0;
603 OSString
* keyUUID
= 0;
604 OSString
* keyStoreUUID
= 0;
606 dev_t hibernate_image_dev
;
612 HIBLOG("sizeof(IOHibernateImageHeader) == %ld\n", sizeof(IOHibernateImageHeader
));
613 if (sizeof(IOHibernateImageHeader
) != 512)
617 vars
->buffer
= (uint8_t *) ioBuffer
->getBytesNoCopy();
618 vars
->bufferHalf
= 0;
619 vars
->bufferOffset
= 0;
620 vars
->bufferSize
= ioBuffer
->getLength() >> 1;
622 extentsData
= OSData::withCapacity(32);
624 ctx
.extents
= extentsData
;
626 vars
->fileRef
= kern_open_file_for_direct_io(filename
,
627 &file_extent_callback
, &ctx
,
629 &hibernate_image_dev
,
633 0, (caddr_t
) gIOHibernateCurrentHeader
,
634 sizeof(IOHibernateImageHeader
));
637 err
= kIOReturnNoSpace
;
640 gIOHibernateFileRef
= vars
->fileRef
;
642 if (kIOHibernateModeSSDInvert
& gIOHibernateMode
)
643 vars
->flags
^= kIOHibernateOptionSSD
;
645 HIBLOG("Opened file %s, size %qd, partition base 0x%qx, maxio %qx ssd %d\n", filename
, ctx
.size
,
646 vars
->block0
, maxiobytes
, kIOHibernateOptionSSD
& vars
->flags
);
647 if (ctx
.size
< 1*1024*1024) // check against image size estimate!
649 err
= kIOReturnNoSpace
;
653 if (maxiobytes
< vars
->bufferSize
)
654 vars
->bufferSize
= maxiobytes
;
656 vars
->extentMap
= (IOPolledFileExtent
*) extentsData
->getBytesNoCopy();
658 part
= IOCopyMediaForDev(block_dev
);
662 err
= part
->callPlatformFunction(PLATFORM_FUNCTION_GET_MEDIA_ENCRYPTION_KEY_UUID
, false,
663 (void *) &keyUUID
, (void *) &keyStoreUUID
, NULL
, NULL
);
664 if ((kIOReturnSuccess
== err
) && keyUUID
&& keyStoreUUID
)
666 // IOLog("got volume key %s\n", keyStoreUUID->getCStringNoCopy());
667 uuid_t volumeKeyUUID
;
668 aks_volume_key_t vek
;
669 static IOService
* sKeyStore
;
670 static const OSSymbol
* sAKSGetKey
;
673 sAKSGetKey
= OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY
);
675 sKeyStore
= (IOService
*) IORegistryEntry::fromPath(AKS_SERVICE_PATH
, gIOServicePlane
);
677 err
= uuid_parse(keyStoreUUID
->getCStringNoCopy(), volumeKeyUUID
);
679 err
= kIOReturnNoResources
;
680 if (kIOReturnSuccess
== err
)
681 err
= sKeyStore
->callPlatformFunction(sAKSGetKey
, true, volumeKeyUUID
, &vek
, NULL
, NULL
);
682 if (kIOReturnSuccess
!= err
)
683 IOLog("volume key err 0x%x\n", err
);
686 size_t bytes
= (kIOHibernateAESKeySize
/ 8);
687 if (vek
.key
.keybytecount
< bytes
)
688 bytes
= vek
.key
.keybytecount
;
689 bcopy(&vek
.key
.keybytes
[0], volumeCryptKey
, bytes
);
691 bzero(&vek
, sizeof(vek
));
695 part
= IOCopyMediaForDev(hibernate_image_dev
);
699 IORegistryEntry
* next
;
700 IORegistryEntry
* child
;
703 vars
->pollers
= OSArray::withCapacity(4);
707 vars
->blockSize
= 512;
711 IOPolledInterface
* poller
;
714 obj
= next
->getProperty(kIOPolledInterfaceSupportKey
);
715 if (kOSBooleanFalse
== obj
)
717 vars
->pollers
->flushCollection();
720 else if ((poller
= OSDynamicCast(IOPolledInterface
, obj
)))
721 vars
->pollers
->setObject(poller
);
722 if ((num
= OSDynamicCast(OSNumber
, next
->getProperty(kIOMediaPreferredBlockSizeKey
))))
723 vars
->blockSize
= num
->unsigned32BitValue();
726 while ((next
= child
->getParentEntry(gIOServicePlane
))
727 && child
->isParent(next
, gIOServicePlane
, true));
729 HIBLOG("hibernate image major %d, minor %d, blocksize %ld, pollers %d\n",
730 major(hibernate_image_dev
), minor(hibernate_image_dev
), (long)vars
->blockSize
, vars
->pollers
->getCount());
731 if (vars
->pollers
->getCount() < kIOHibernateMinPollersNeeded
)
734 err
= IOHibernatePollerProbe(vars
, (IOService
*) part
);
735 if (kIOReturnSuccess
!= err
)
738 err
= IOHibernatePollerOpen(vars
, kIOPolledPreflightState
, ioBuffer
);
739 if (kIOReturnSuccess
!= err
)
743 *fileExtents
= extentsData
;
747 if ((extentsData
->getLength() >= sizeof(IOPolledFileExtent
)))
749 char str2
[24 + sizeof(uuid_string_t
) + 2];
751 #if defined(__i386__) || defined(__x86_64__)
752 if (!gIOCreateEFIDevicePathSymbol
)
753 gIOCreateEFIDevicePathSymbol
= OSSymbol::withCString("CreateEFIDevicePath");
756 snprintf(str2
, sizeof(str2
), "%qx:%s",
757 vars
->extentMap
[0].start
, keyUUID
->getCStringNoCopy());
759 snprintf(str2
, sizeof(str2
), "%qx", vars
->extentMap
[0].start
);
761 err
= IOService::getPlatform()->callPlatformFunction(
762 gIOCreateEFIDevicePathSymbol
, false,
763 (void *) part
, (void *) str2
,
764 (void *) (uintptr_t) true, (void *) &data
);
767 int len
= sizeof(str1
);
769 if (!part
->getPath(str1
, &len
, gIODTPlane
))
770 err
= kIOReturnNotFound
;
773 snprintf(str2
, sizeof(str2
), ",%qx", vars
->extentMap
[0].start
);
774 // (strip the plane name)
775 char * tail
= strchr(str1
, ':');
778 data
= OSData::withBytes(tail
+ 1, strlen(tail
+ 1));
779 data
->appendBytes(str2
, strlen(str2
));
782 if (kIOReturnSuccess
== err
)
785 HIBLOG("error 0x%x getting path\n", err
);
790 if (kIOReturnSuccess
!= err
)
792 HIBLOG("error 0x%x opening hibernation file\n", err
);
795 kern_close_file_for_direct_io(vars
->fileRef
, 0, 0, 0);
796 gIOHibernateFileRef
= vars
->fileRef
= NULL
;
807 IOPolledFileClose( IOPolledFileIOVars
* vars
)
811 IOHibernatePollerClose(vars
, kIOPolledPostflightState
);
812 vars
->pollers
->release();
815 bzero(vars
, sizeof(IOPolledFileIOVars
));
817 return (kIOReturnSuccess
);
821 IOPolledFileSeek(IOPolledFileIOVars
* vars
, uint64_t position
)
823 IOPolledFileExtent
* extentMap
;
825 extentMap
= vars
->extentMap
;
827 vars
->position
= position
;
829 while (position
>= extentMap
->length
)
831 position
-= extentMap
->length
;
835 vars
->currentExtent
= extentMap
;
836 vars
->extentRemaining
= extentMap
->length
- position
;
837 vars
->extentPosition
= vars
->position
- position
;
839 if (vars
->bufferSize
<= vars
->extentRemaining
)
840 vars
->bufferLimit
= vars
->bufferSize
;
842 vars
->bufferLimit
= vars
->extentRemaining
;
844 return (kIOReturnSuccess
);
848 IOPolledFileWrite(IOPolledFileIOVars
* vars
,
849 const uint8_t * bytes
, IOByteCount size
,
850 hibernate_cryptvars_t
* cryptvars
)
852 IOReturn err
= kIOReturnSuccess
;
860 // seek to end of block & flush
861 size
= vars
->position
& (vars
->blockSize
- 1);
863 size
= vars
->blockSize
- size
;
865 // use some garbage for the fill
866 bytes
= vars
->buffer
+ vars
->bufferOffset
;
869 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
877 bcopy(bytes
, vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
881 bzero(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
884 vars
->bufferOffset
+= copy
;
885 vars
->position
+= copy
;
887 if (flush
&& vars
->bufferOffset
)
889 uint64_t offset
= (vars
->position
- vars
->bufferOffset
890 - vars
->extentPosition
+ vars
->currentExtent
->start
);
891 uint32_t length
= (vars
->bufferOffset
);
894 if (cryptvars
&& vars
->encryptStart
895 && (vars
->position
> vars
->encryptStart
)
896 && ((vars
->position
- length
) < vars
->encryptEnd
))
898 AbsoluteTime startTime
, endTime
;
900 uint32_t encryptLen
, encryptStart
;
901 encryptLen
= vars
->position
- vars
->encryptStart
;
902 if (encryptLen
> length
)
904 encryptStart
= length
- encryptLen
;
905 if (vars
->position
> vars
->encryptEnd
)
906 encryptLen
-= (vars
->position
- vars
->encryptEnd
);
908 clock_get_uptime(&startTime
);
910 // encrypt the buffer
911 aes_encrypt_cbc(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
912 &cryptvars
->aes_iv
[0],
913 encryptLen
/ AES_BLOCK_SIZE
,
914 vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
915 &cryptvars
->ctx
.encrypt
);
917 clock_get_uptime(&endTime
);
918 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
);
919 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
);
920 vars
->cryptBytes
+= encryptLen
;
922 // save initial vector for following encrypts
923 bcopy(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
+ encryptLen
- AES_BLOCK_SIZE
,
924 &cryptvars
->aes_iv
[0],
931 err
= IOHibernatePollerIODone(vars
, true);
932 if (kIOReturnSuccess
!= err
)
936 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
937 //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length);
939 err
= IOHibernatePollerIO(vars
, kIOPolledWrite
, vars
->bufferHalf
, offset
, length
);
940 if (kIOReturnSuccess
!= err
)
944 vars
->extentRemaining
-= vars
->bufferOffset
;
945 if (!vars
->extentRemaining
)
947 vars
->currentExtent
++;
948 vars
->extentRemaining
= vars
->currentExtent
->length
;
949 vars
->extentPosition
= vars
->position
;
950 if (!vars
->extentRemaining
)
952 err
= kIOReturnOverrun
;
957 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
958 vars
->bufferOffset
= 0;
959 if (vars
->bufferSize
<= vars
->extentRemaining
)
960 vars
->bufferLimit
= vars
->bufferSize
;
962 vars
->bufferLimit
= vars
->extentRemaining
;
973 IOPolledFileRead(IOPolledFileIOVars
* vars
,
974 uint8_t * bytes
, IOByteCount size
,
975 hibernate_cryptvars_t
* cryptvars
)
977 IOReturn err
= kIOReturnSuccess
;
980 // bytesWritten += size;
984 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
990 bcopy(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, bytes
, copy
);
994 vars
->bufferOffset
+= copy
;
995 // vars->position += copy;
997 if ((vars
->bufferOffset
== vars
->bufferLimit
) && (vars
->position
< vars
->readEnd
))
1001 err
= IOHibernatePollerIODone(vars
, false);
1002 if (kIOReturnSuccess
!= err
)
1008 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
1010 vars
->position
+= vars
->lastRead
;
1011 vars
->extentRemaining
-= vars
->lastRead
;
1012 vars
->bufferLimit
= vars
->lastRead
;
1014 if (!vars
->extentRemaining
)
1016 vars
->currentExtent
++;
1017 vars
->extentRemaining
= vars
->currentExtent
->length
;
1018 vars
->extentPosition
= vars
->position
;
1019 if (!vars
->extentRemaining
)
1021 err
= kIOReturnOverrun
;
1027 uint64_t lastReadLength
= vars
->lastRead
;
1028 uint64_t offset
= (vars
->position
1029 - vars
->extentPosition
+ vars
->currentExtent
->start
);
1030 if (vars
->extentRemaining
<= vars
->bufferSize
)
1031 length
= vars
->extentRemaining
;
1033 length
= vars
->bufferSize
;
1034 if ((length
+ vars
->position
) > vars
->readEnd
)
1035 length
= vars
->readEnd
- vars
->position
;
1037 vars
->lastRead
= length
;
1040 //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length);
1041 err
= IOHibernatePollerIO(vars
, kIOPolledRead
, vars
->bufferHalf
, offset
, length
);
1042 if (kIOReturnSuccess
!= err
)
1047 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
1048 vars
->bufferOffset
= 0;
1053 uint8_t thisVector
[AES_BLOCK_SIZE
];
1054 AbsoluteTime startTime
, endTime
;
1056 // save initial vector for following decrypts
1057 bcopy(&cryptvars
->aes_iv
[0], &thisVector
[0], AES_BLOCK_SIZE
);
1058 bcopy(vars
->buffer
+ vars
->bufferHalf
+ lastReadLength
- AES_BLOCK_SIZE
,
1059 &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
);
1061 // decrypt the buffer
1062 clock_get_uptime(&startTime
);
1064 aes_decrypt_cbc(vars
->buffer
+ vars
->bufferHalf
,
1066 lastReadLength
/ AES_BLOCK_SIZE
,
1067 vars
->buffer
+ vars
->bufferHalf
,
1068 &cryptvars
->ctx
.decrypt
);
1070 clock_get_uptime(&endTime
);
1071 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
);
1072 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
);
1073 vars
->cryptBytes
+= lastReadLength
;
1083 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1086 IOHibernateSystemSleep(void)
1094 IOHibernateVars
* vars
= &gIOHibernateVars
;
1096 if (vars
->fileVars
&& vars
->fileVars
->fileRef
)
1097 // already on the way down
1098 return (kIOReturnSuccess
);
1100 gIOHibernateState
= kIOHibernateStateInactive
;
1102 gIOHibernateDebugFlags
= 0;
1103 if (kIOLogHibernate
& gIOKitDebug
)
1104 gIOHibernateDebugFlags
|= kIOHibernateDebugRestoreLogs
;
1106 if (IOService::getPMRootDomain()->getHibernateSettings(
1107 &gIOHibernateMode
, &gIOHibernateFreeRatio
, &gIOHibernateFreeTime
))
1109 if (kIOHibernateModeSleep
& gIOHibernateMode
)
1110 // default to discard clean for safe sleep
1111 gIOHibernateMode
^= (kIOHibernateModeDiscardCleanInactive
1112 | kIOHibernateModeDiscardCleanActive
);
1115 if ((obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey
)))
1117 if ((str
= OSDynamicCast(OSString
, obj
)))
1118 strlcpy(gIOHibernateFilename
, str
->getCStringNoCopy(),
1119 sizeof(gIOHibernateFilename
));
1123 if (!gIOHibernateMode
|| !gIOHibernateFilename
[0])
1124 return (kIOReturnUnsupported
);
1126 HIBLOG("hibernate image path: %s\n", gIOHibernateFilename
);
1131 vars
->srcBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,
1132 4 * page_size
, page_size
);
1133 vars
->ioBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,
1134 2 * kDefaultIOSize
, page_size
);
1136 vars
->handoffBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,
1137 ptoa_64(gIOHibernateHandoffPageCount
), page_size
);
1139 if (!vars
->srcBuffer
|| !vars
->ioBuffer
|| !vars
->handoffBuffer
)
1141 err
= kIOReturnNoMemory
;
1145 // open & invalidate the image file
1146 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderInvalidSignature
;
1147 err
= IOPolledFileOpen(gIOHibernateFilename
, vars
->ioBuffer
,
1148 &vars
->fileVars
, &vars
->fileExtents
, &data
,
1149 &vars
->volumeCryptKey
[0]);
1150 if (KERN_SUCCESS
!= err
)
1152 HIBLOG("IOPolledFileOpen(%x)\n", err
);
1156 bzero(gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
));
1157 gIOHibernateCurrentHeader
->debugFlags
= gIOHibernateDebugFlags
;
1158 dsSSD
= ((0 != (kIOHibernateOptionSSD
& vars
->fileVars
->flags
))
1159 && (kOSBooleanTrue
== IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey
)));
1162 gIOHibernateCurrentHeader
->options
|=
1163 kIOHibernateOptionSSD
1164 | kIOHibernateOptionColor
;
1166 #if defined(__i386__) || defined(__x86_64__)
1167 if (!uuid_is_null(vars
->volumeCryptKey
) &&
1168 (kOSBooleanTrue
!= IOService::getPMRootDomain()->getProperty(kIOPMDestroyFVKeyOnStandbyKey
)))
1170 uintptr_t smcVars
[2];
1171 smcVars
[0] = sizeof(vars
->volumeCryptKey
);
1172 smcVars
[1] = (uintptr_t)(void *) &vars
->volumeCryptKey
[0];
1174 IOService::getPMRootDomain()->setProperty(kIOHibernateSMCVariablesKey
, smcVars
, sizeof(smcVars
));
1175 bzero(smcVars
, sizeof(smcVars
));
1181 gIOHibernateCurrentHeader
->options
|= kIOHibernateOptionProgress
;
1184 boolean_t encryptedswap
;
1185 AbsoluteTime startTime
, endTime
;
1188 clock_get_uptime(&startTime
);
1189 err
= hibernate_setup(gIOHibernateCurrentHeader
,
1190 gIOHibernateFreeRatio
, gIOHibernateFreeTime
,
1192 &vars
->page_list
, &vars
->page_list_wired
, &vars
->page_list_pal
, &encryptedswap
);
1193 clock_get_uptime(&endTime
);
1194 SUB_ABSOLUTETIME(&endTime
, &startTime
);
1195 absolutetime_to_nanoseconds(endTime
, &nsec
);
1196 HIBLOG("hibernate_setup(%d) took %qd ms\n", err
, nsec
/ 1000000ULL);
1198 if (KERN_SUCCESS
!= err
)
1201 if (encryptedswap
|| !uuid_is_null(vars
->volumeCryptKey
))
1202 gIOHibernateMode
^= kIOHibernateModeEncrypt
;
1204 if (kIOHibernateOptionProgress
& gIOHibernateCurrentHeader
->options
)
1206 vars
->videoAllocSize
= kVideoMapSize
;
1207 if (KERN_SUCCESS
!= kmem_alloc_pageable(kernel_map
, &vars
->videoMapping
, vars
->videoAllocSize
))
1208 vars
->videoMapping
= 0;
1211 // generate crypt keys
1212 for (uint32_t i
= 0; i
< sizeof(vars
->wiredCryptKey
); i
++)
1213 vars
->wiredCryptKey
[i
] = random();
1214 for (uint32_t i
= 0; i
< sizeof(vars
->cryptKey
); i
++)
1215 vars
->cryptKey
[i
] = random();
1219 IORegistryEntry
* regEntry
;
1220 if (!gIOOptionsEntry
)
1222 regEntry
= IORegistryEntry::fromPath("/options", gIODTPlane
);
1223 gIOOptionsEntry
= OSDynamicCast(IODTNVRAM
, regEntry
);
1224 if (regEntry
&& !gIOOptionsEntry
)
1225 regEntry
->release();
1227 if (!gIOChosenEntry
)
1228 gIOChosenEntry
= IORegistryEntry::fromPath("/chosen", gIODTPlane
);
1230 if (gIOOptionsEntry
)
1232 const OSSymbol
* sym
;
1234 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey
);
1237 gIOOptionsEntry
->setProperty(sym
, data
);
1242 #if defined(__i386__) || defined(__x86_64__)
1243 struct AppleRTCHibernateVars
1245 uint8_t signature
[4];
1247 uint8_t booterSignature
[20];
1248 uint8_t wiredCryptKey
[16];
1250 AppleRTCHibernateVars rtcVars
;
1252 rtcVars
.signature
[0] = 'A';
1253 rtcVars
.signature
[1] = 'A';
1254 rtcVars
.signature
[2] = 'P';
1255 rtcVars
.signature
[3] = 'L';
1256 rtcVars
.revision
= 1;
1257 bcopy(&vars
->wiredCryptKey
[0], &rtcVars
.wiredCryptKey
[0], sizeof(rtcVars
.wiredCryptKey
));
1258 if (gIOHibernateBootSignature
[0])
1262 for (uint32_t i
= 0;
1263 (c
= gIOHibernateBootSignature
[i
]) && (i
< (sizeof(rtcVars
.booterSignature
) << 1));
1274 value
= (value
<< 4) | c
;
1276 rtcVars
.booterSignature
[i
>> 1] = value
;
1279 data
= OSData::withBytes(&rtcVars
, sizeof(rtcVars
));
1282 if (!gIOHibernateRTCVariablesKey
)
1283 gIOHibernateRTCVariablesKey
= OSSymbol::withCStringNoCopy(kIOHibernateRTCVariablesKey
);
1284 if (gIOHibernateRTCVariablesKey
)
1285 IOService::getPMRootDomain()->setProperty(gIOHibernateRTCVariablesKey
, data
);
1287 if( gIOOptionsEntry
)
1289 if( gIOHibernateMode
& kIOHibernateModeSwitch
)
1291 const OSSymbol
*sym
;
1292 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootSwitchVarsKey
);
1295 gIOOptionsEntry
->setProperty(sym
, data
); /* intentional insecure backup of rtc boot vars */
1305 data
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMachineSignatureKey
));
1307 gIOHibernateCurrentHeader
->machineSignature
= *((UInt32
*)data
->getBytesNoCopy());
1311 if (!gIOHibernateBoot0082Data
)
1313 data
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty("boot-device-path"));
1316 // AppleNVRAM_EFI_LOAD_OPTION
1318 uint32_t Attributes
;
1319 uint16_t FilePathLength
;
1322 loadOptionHeader
.Attributes
= 1;
1323 loadOptionHeader
.FilePathLength
= data
->getLength();
1324 loadOptionHeader
.Desc
= 0;
1325 gIOHibernateBoot0082Data
= OSData::withCapacity(sizeof(loadOptionHeader
) + loadOptionHeader
.FilePathLength
);
1326 if (gIOHibernateBoot0082Data
)
1328 gIOHibernateBoot0082Data
->appendBytes(&loadOptionHeader
, sizeof(loadOptionHeader
));
1329 gIOHibernateBoot0082Data
->appendBytes(data
);
1333 if (!gIOHibernateBoot0082Key
)
1334 gIOHibernateBoot0082Key
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:Boot0082");
1335 if (!gIOHibernateBootNextKey
)
1336 gIOHibernateBootNextKey
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:BootNext");
1337 if (!gIOHibernateBootNextData
)
1339 uint16_t bits
= 0x0082;
1340 gIOHibernateBootNextData
= OSData::withBytes(&bits
, sizeof(bits
));
1342 if (gIOHibernateBoot0082Key
&& gIOHibernateBoot0082Data
&& gIOHibernateBootNextKey
&& gIOHibernateBootNextData
)
1344 gIOHibernateBootNextSave
= gIOOptionsEntry
->copyProperty(gIOHibernateBootNextKey
);
1345 gIOOptionsEntry
->setProperty(gIOHibernateBoot0082Key
, gIOHibernateBoot0082Data
);
1346 gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextData
);
1350 #else /* !i386 && !x86_64 */
1351 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
1353 data
= OSData::withBytes(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
));
1354 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKeyKey
);
1356 gIOOptionsEntry
->setProperty(sym
, data
);
1361 if (false && gIOHibernateBootSignature
[0])
1363 data
= OSData::withCapacity(16);
1364 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey
);
1369 for (uint32_t i
= 0; (c
= gIOHibernateBootSignature
[i
]); i
++)
1379 value
= (value
<< 4) | c
;
1381 data
->appendBytes(&value
, sizeof(value
));
1383 gIOOptionsEntry
->setProperty(sym
, data
);
1391 if (!vars
->haveFastBoot
)
1393 // set boot volume to zero
1394 IODTPlatformExpert
* platform
= OSDynamicCast(IODTPlatformExpert
, IOService::getPlatform());
1395 if (platform
&& (kIOReturnSuccess
== platform
->readXPRAM(kXPRamAudioVolume
,
1396 &vars
->saveBootAudioVolume
, sizeof(vars
->saveBootAudioVolume
))))
1399 newVolume
= vars
->saveBootAudioVolume
& 0xf8;
1400 platform
->writeXPRAM(kXPRamAudioVolume
,
1401 &newVolume
, sizeof(newVolume
));
1404 #endif /* !i386 && !x86_64 */
1408 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderSignature
;
1409 gIOHibernateState
= kIOHibernateStateHibernating
;
1416 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1418 DECLARE_IOHIBERNATEPROGRESSALPHA
1421 ProgressInit(hibernate_graphics_t
* display
, uint8_t * screen
, uint8_t * saveunder
, uint32_t savelen
)
1423 uint32_t rowBytes
, pixelShift
;
1426 uint32_t alpha
, in
, color
, result
;
1428 uint32_t saveindex
[kIOHibernateProgressCount
] = { 0 };
1430 rowBytes
= display
->rowBytes
;
1431 pixelShift
= display
->depth
>> 4;
1432 if (pixelShift
< 1) return;
1434 screen
+= ((display
->width
1435 - kIOHibernateProgressCount
* (kIOHibernateProgressWidth
+ kIOHibernateProgressSpacing
)) << (pixelShift
- 1))
1436 + (display
->height
- kIOHibernateProgressOriginY
- kIOHibernateProgressHeight
) * rowBytes
;
1438 for (y
= 0; y
< kIOHibernateProgressHeight
; y
++)
1440 out
= screen
+ y
* rowBytes
;
1441 for (blob
= 0; blob
< kIOHibernateProgressCount
; blob
++)
1443 color
= blob
? kIOHibernateProgressDarkGray
: kIOHibernateProgressMidGray
;
1444 for (x
= 0; x
< kIOHibernateProgressWidth
; x
++)
1446 alpha
= gIOHibernateProgressAlpha
[y
][x
];
1452 if (1 == pixelShift
)
1454 in
= *((uint16_t *)out
) & 0x1f; // 16
1455 in
= (in
<< 3) | (in
>> 2);
1458 in
= *((uint32_t *)out
) & 0xff; // 32
1459 saveunder
[blob
* kIOHibernateProgressSaveUnderSize
+ saveindex
[blob
]++] = in
;
1460 result
= ((255 - alpha
) * in
+ alpha
* result
+ 0xff) >> 8;
1462 if (1 == pixelShift
)
1465 *((uint16_t *)out
) = (result
<< 10) | (result
<< 5) | result
; // 16
1468 *((uint32_t *)out
) = (result
<< 16) | (result
<< 8) | result
; // 32
1470 out
+= (1 << pixelShift
);
1472 out
+= (kIOHibernateProgressSpacing
<< pixelShift
);
1479 ProgressUpdate(hibernate_graphics_t
* display
, uint8_t * screen
, int32_t firstBlob
, int32_t select
)
1481 uint32_t rowBytes
, pixelShift
;
1483 int32_t blob
, lastBlob
;
1484 uint32_t alpha
, in
, color
, result
;
1486 uint32_t saveindex
[kIOHibernateProgressCount
] = { 0 };
1488 pixelShift
= display
->depth
>> 4;
1492 rowBytes
= display
->rowBytes
;
1494 screen
+= ((display
->width
1495 - kIOHibernateProgressCount
* (kIOHibernateProgressWidth
+ kIOHibernateProgressSpacing
)) << (pixelShift
- 1))
1496 + (display
->height
- kIOHibernateProgressOriginY
- kIOHibernateProgressHeight
) * rowBytes
;
1498 lastBlob
= (select
< kIOHibernateProgressCount
) ? select
: (kIOHibernateProgressCount
- 1);
1500 screen
+= (firstBlob
* (kIOHibernateProgressWidth
+ kIOHibernateProgressSpacing
)) << pixelShift
;
1502 for (y
= 0; y
< kIOHibernateProgressHeight
; y
++)
1504 out
= screen
+ y
* rowBytes
;
1505 for (blob
= firstBlob
; blob
<= lastBlob
; blob
++)
1507 color
= (blob
< select
) ? kIOHibernateProgressLightGray
: kIOHibernateProgressMidGray
;
1508 for (x
= 0; x
< kIOHibernateProgressWidth
; x
++)
1510 alpha
= gIOHibernateProgressAlpha
[y
][x
];
1516 in
= display
->progressSaveUnder
[blob
][saveindex
[blob
]++];
1517 result
= ((255 - alpha
) * in
+ alpha
* result
+ 0xff) / 255;
1519 if (1 == pixelShift
)
1522 *((uint16_t *)out
) = (result
<< 10) | (result
<< 5) | result
; // 16
1525 *((uint32_t *)out
) = (result
<< 16) | (result
<< 8) | result
; // 32
1527 out
+= (1 << pixelShift
);
1529 out
+= (kIOHibernateProgressSpacing
<< pixelShift
);
1534 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1537 IOHibernateSystemHasSlept(void)
1539 IOHibernateVars
* vars
= &gIOHibernateVars
;
1543 obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernatePreviewBufferKey
);
1544 vars
->previewBuffer
= OSDynamicCast(IOMemoryDescriptor
, obj
);
1545 if (obj
&& !vars
->previewBuffer
)
1548 vars
->consoleMapping
= NULL
;
1549 if (vars
->previewBuffer
&& (kIOReturnSuccess
!= vars
->previewBuffer
->prepare()))
1551 vars
->previewBuffer
->release();
1552 vars
->previewBuffer
= 0;
1555 if ((kIOHibernateOptionProgress
& gIOHibernateCurrentHeader
->options
)
1556 && vars
->previewBuffer
1557 && (data
= OSDynamicCast(OSData
,
1558 IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey
))))
1560 UInt32 flags
= *((UInt32
*)data
->getBytesNoCopy());
1561 HIBPRINT("kIOHibernatePreviewActiveKey %08lx\n", (long)flags
);
1563 IOService::getPMRootDomain()->removeProperty(kIOHibernatePreviewActiveKey
);
1565 if (kIOHibernatePreviewUpdates
& flags
)
1567 PE_Video consoleInfo
;
1568 hibernate_graphics_t
* graphicsInfo
= gIOHibernateGraphicsInfo
;
1570 IOService::getPlatform()->getConsoleInfo(&consoleInfo
);
1572 graphicsInfo
->width
= consoleInfo
.v_width
;
1573 graphicsInfo
->height
= consoleInfo
.v_height
;
1574 graphicsInfo
->rowBytes
= consoleInfo
.v_rowBytes
;
1575 graphicsInfo
->depth
= consoleInfo
.v_depth
;
1576 vars
->consoleMapping
= (uint8_t *) consoleInfo
.v_baseAddr
;
1578 HIBPRINT("video %p %d %d %d\n",
1579 vars
->consoleMapping
, graphicsInfo
->depth
,
1580 graphicsInfo
->width
, graphicsInfo
->height
);
1581 if (vars
->consoleMapping
)
1582 ProgressInit(graphicsInfo
, vars
->consoleMapping
,
1583 &graphicsInfo
->progressSaveUnder
[0][0], sizeof(graphicsInfo
->progressSaveUnder
));
1587 if (gIOOptionsEntry
)
1588 gIOOptionsEntry
->sync();
1590 return (kIOReturnSuccess
);
1593 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1595 static DeviceTreeNode
*
1596 MergeDeviceTree(DeviceTreeNode
* entry
, IORegistryEntry
* regEntry
)
1598 DeviceTreeNodeProperty
* prop
;
1599 DeviceTreeNode
* child
;
1600 IORegistryEntry
* childRegEntry
;
1601 const char * nameProp
;
1602 unsigned int propLen
, idx
;
1604 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
1605 for (idx
= 0; idx
< entry
->nProperties
; idx
++)
1607 if (regEntry
&& (0 != strcmp("name", prop
->name
)))
1609 regEntry
->setProperty((const char *) prop
->name
, (void *) (prop
+ 1), prop
->length
);
1610 // HIBPRINT("%s: %s, %d\n", regEntry->getName(), prop->name, prop->length);
1612 prop
= (DeviceTreeNodeProperty
*) (((uintptr_t)(prop
+ 1)) + ((prop
->length
+ 3) & ~3));
1615 child
= (DeviceTreeNode
*) prop
;
1616 for (idx
= 0; idx
< entry
->nChildren
; idx
++)
1618 if (kSuccess
!= DTGetProperty(child
, "name", (void **) &nameProp
, &propLen
))
1620 childRegEntry
= regEntry
? regEntry
->childFromPath(nameProp
, gIODTPlane
) : NULL
;
1621 // HIBPRINT("%s == %p\n", nameProp, childRegEntry);
1622 child
= MergeDeviceTree(child
, childRegEntry
);
1628 IOHibernateSystemWake(void)
1630 IOHibernateVars
* vars
= &gIOHibernateVars
;
1632 hibernate_teardown(vars
->page_list
, vars
->page_list_wired
);
1634 if (vars
->videoMapping
)
1636 if (vars
->videoMapSize
)
1638 IOUnmapPages(kernel_map
, vars
->videoMapping
, vars
->videoMapSize
);
1639 if (vars
->videoAllocSize
)
1641 kmem_free(kernel_map
, trunc_page(vars
->videoMapping
), vars
->videoAllocSize
);
1644 if (vars
->previewBuffer
)
1646 vars
->previewBuffer
->release();
1647 vars
->previewBuffer
= 0;
1650 if (kIOHibernateStateWakingFromHibernate
== gIOHibernateState
)
1652 IOService::getPMRootDomain()->setProperty(kIOHibernateOptionsKey
,
1653 gIOHibernateCurrentHeader
->options
, 32);
1657 IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey
);
1660 if ((kIOHibernateStateWakingFromHibernate
== gIOHibernateState
)
1661 && (kIOHibernateGfxStatusUnknown
!= gIOHibernateGraphicsInfo
->gfxStatus
))
1663 IOService::getPMRootDomain()->setProperty(kIOHibernateGfxStatusKey
,
1664 &gIOHibernateGraphicsInfo
->gfxStatus
,
1665 sizeof(gIOHibernateGraphicsInfo
->gfxStatus
));
1669 IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey
);
1675 IOPolledFileClose(vars
->fileVars
);
1678 // invalidate nvram properties - (gIOOptionsEntry != 0) => nvram was touched
1680 #if defined(__i386__) || defined(__x86_64__)
1681 IOService::getPMRootDomain()->removeProperty(gIOHibernateRTCVariablesKey
);
1682 IOService::getPMRootDomain()->removeProperty(kIOHibernateSMCVariablesKey
);
1685 * Hibernate variable is written to NVRAM on platforms in which RtcRam
1686 * is not backed by coin cell. Remove Hibernate data from NVRAM.
1688 if (gIOOptionsEntry
) {
1690 if (gIOHibernateRTCVariablesKey
) {
1691 if (gIOOptionsEntry
->getProperty(gIOHibernateRTCVariablesKey
)) {
1692 gIOOptionsEntry
->removeProperty(gIOHibernateRTCVariablesKey
);
1696 if (gIOHibernateBootNextKey
)
1698 if (gIOHibernateBootNextSave
)
1700 gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextSave
);
1701 gIOHibernateBootNextSave
->release();
1702 gIOHibernateBootNextSave
= NULL
;
1705 gIOOptionsEntry
->removeProperty(gIOHibernateBootNextKey
);
1707 gIOOptionsEntry
->sync();
1711 if (vars
->srcBuffer
)
1712 vars
->srcBuffer
->release();
1714 vars
->ioBuffer
->release();
1715 bzero(&gIOHibernateHandoffPages
[0], gIOHibernateHandoffPageCount
* sizeof(gIOHibernateHandoffPages
[0]));
1716 if (vars
->handoffBuffer
)
1718 IOHibernateHandoff
* handoff
;
1720 for (handoff
= (IOHibernateHandoff
*) vars
->handoffBuffer
->getBytesNoCopy();
1722 handoff
= (IOHibernateHandoff
*) &handoff
->data
[handoff
->bytecount
])
1724 // HIBPRINT("handoff %p, %x, %x\n", handoff, handoff->type, handoff->bytecount);
1725 uint8_t * data
= &handoff
->data
[0];
1726 switch (handoff
->type
)
1728 case kIOHibernateHandoffTypeEnd
:
1732 case kIOHibernateHandoffTypeDeviceTree
:
1733 MergeDeviceTree((DeviceTreeNode
*) data
, IOService::getServiceRoot());
1736 case kIOHibernateHandoffTypeKeyStore
:
1737 #if defined(__i386__) || defined(__x86_64__)
1739 IOBufferMemoryDescriptor
*
1740 md
= IOBufferMemoryDescriptor::withBytes(data
, handoff
->bytecount
, kIODirectionOutIn
);
1743 IOSetKeyStoreData(md
);
1750 done
= (kIOHibernateHandoffType
!= (handoff
->type
& 0xFFFF0000));
1754 vars
->handoffBuffer
->release();
1756 if (vars
->fileExtents
)
1757 vars
->fileExtents
->release();
1759 bzero(vars
, sizeof(*vars
));
1761 // gIOHibernateState = kIOHibernateStateInactive; // leave it for post wake code to see
1763 return (kIOReturnSuccess
);
1767 IOHibernateSystemPostWake(void)
1769 if (gIOHibernateFileRef
)
1771 // invalidate & close the image file
1772 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderInvalidSignature
;
1773 kern_close_file_for_direct_io(gIOHibernateFileRef
,
1774 0, (caddr_t
) gIOHibernateCurrentHeader
,
1775 sizeof(IOHibernateImageHeader
));
1776 gIOHibernateFileRef
= 0;
1778 return (kIOReturnSuccess
);
1781 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1783 SYSCTL_STRING(_kern
, OID_AUTO
, hibernatefile
,
1784 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1785 gIOHibernateFilename
, sizeof(gIOHibernateFilename
), "");
1786 SYSCTL_STRING(_kern
, OID_AUTO
, bootsignature
,
1787 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1788 gIOHibernateBootSignature
, sizeof(gIOHibernateBootSignature
), "");
1789 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatemode
,
1790 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
1791 &gIOHibernateMode
, 0, "");
1794 IOHibernateSystemInit(IOPMrootDomain
* rootDomain
)
1796 OSData
* data
= OSData::withBytesNoCopy(&gIOHibernateState
, sizeof(gIOHibernateState
));
1799 rootDomain
->setProperty(kIOHibernateStateKey
, data
);
1803 if (PE_parse_boot_argn("hfile", gIOHibernateFilename
, sizeof(gIOHibernateFilename
)))
1804 gIOHibernateMode
= kIOHibernateModeOn
;
1806 gIOHibernateFilename
[0] = 0;
1808 sysctl_register_oid(&sysctl__kern_hibernatefile
);
1809 sysctl_register_oid(&sysctl__kern_bootsignature
);
1810 sysctl_register_oid(&sysctl__kern_hibernatemode
);
1814 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1817 hibernate_setup_for_wake(void)
1821 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1823 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
1826 no_encrypt_page(vm_offset_t ppnum
)
1828 if (pmap_is_noencrypt((ppnum_t
)ppnum
) == TRUE
)
1835 uint32_t wired_pages_encrypted
= 0;
1836 uint32_t dirty_pages_encrypted
= 0;
1837 uint32_t wired_pages_clear
= 0;
1840 hibernate_pal_callback(void *vars_arg
, vm_offset_t addr
)
1842 IOHibernateVars
*vars
= (IOHibernateVars
*)vars_arg
;
1843 /* Make sure it's not in either of the save lists */
1844 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
, atop_64(addr
), 1, kIOHibernatePageStateFree
);
1846 /* Set it in the bitmap of pages owned by the PAL */
1847 hibernate_page_bitset(vars
->page_list_pal
, TRUE
, atop_64(addr
));
1850 static struct hibernate_cryptvars_t
*local_cryptvars
;
1853 hibernate_pal_write(void *buffer
, size_t size
)
1855 IOHibernateVars
* vars
= &gIOHibernateVars
;
1857 IOReturn err
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *)buffer
, size
, local_cryptvars
);
1858 if (kIOReturnSuccess
!= err
) {
1859 kprintf("epic hibernate fail! %d\n", err
);
1868 hibernate_write_image(void)
1870 IOHibernateImageHeader
* header
= gIOHibernateCurrentHeader
;
1871 IOHibernateVars
* vars
= &gIOHibernateVars
;
1872 IOPolledFileExtent
* fileExtents
;
1874 C_ASSERT(sizeof(IOHibernateImageHeader
) == 512);
1876 uint32_t pageCount
, pagesDone
;
1878 vm_offset_t ppnum
, page
;
1882 IOByteCount pageCompressedSize
;
1883 uint64_t compressedSize
, uncompressedSize
;
1884 uint64_t image1Size
= 0;
1885 uint32_t bitmap_size
;
1886 bool iterDone
, pollerOpen
, needEncrypt
;
1887 uint32_t restore1Sum
, sum
, sum1
, sum2
;
1890 uint32_t pageAndCount
[2];
1894 AbsoluteTime startTime
, endTime
;
1895 AbsoluteTime allTime
, compTime
;
1898 uint32_t lastProgressStamp
= 0;
1899 uint32_t progressStamp
;
1900 uint32_t blob
, lastBlob
= (uint32_t) -1L;
1902 hibernate_cryptvars_t _cryptvars
;
1903 hibernate_cryptvars_t
* cryptvars
= 0;
1905 wired_pages_encrypted
= 0;
1906 dirty_pages_encrypted
= 0;
1907 wired_pages_clear
= 0;
1909 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
|| !vars
->fileExtents
)
1910 return (false /* sleep */ );
1912 if (kIOHibernateModeSleep
& gIOHibernateMode
)
1913 kdebug_enable
= save_kdebug_enable
;
1915 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_START
, 0, 0, 0, 0, 0);
1916 IOService::getPMRootDomain()->tracePoint(kIOPMTracePointHibernate
);
1918 restore1Sum
= sum1
= sum2
= 0;
1920 hibernate_pal_prepare();
1923 // encryption data. "iv" is the "initial vector".
1924 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
1926 static const unsigned char first_iv
[AES_BLOCK_SIZE
]
1927 = { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c,
1928 0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda };
1930 cryptvars
= &gIOHibernateCryptWakeContext
;
1931 bzero(cryptvars
, sizeof(hibernate_cryptvars_t
));
1932 aes_encrypt_key(vars
->cryptKey
,
1933 kIOHibernateAESKeySize
,
1934 &cryptvars
->ctx
.encrypt
);
1935 aes_decrypt_key(vars
->cryptKey
,
1936 kIOHibernateAESKeySize
,
1937 &cryptvars
->ctx
.decrypt
);
1939 cryptvars
= &_cryptvars
;
1940 bzero(cryptvars
, sizeof(hibernate_cryptvars_t
));
1941 for (pageCount
= 0; pageCount
< sizeof(vars
->wiredCryptKey
); pageCount
++)
1942 vars
->wiredCryptKey
[pageCount
] ^= vars
->volumeCryptKey
[pageCount
];
1943 bzero(&vars
->volumeCryptKey
[0], sizeof(vars
->volumeCryptKey
));
1944 aes_encrypt_key(vars
->wiredCryptKey
,
1945 kIOHibernateAESKeySize
,
1946 &cryptvars
->ctx
.encrypt
);
1948 bcopy(&first_iv
[0], &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
);
1949 bzero(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
));
1950 bzero(&vars
->cryptKey
[0], sizeof(vars
->cryptKey
));
1952 local_cryptvars
= cryptvars
;
1956 hibernate_setup_for_wake();
1958 hibernate_page_list_setall(vars
->page_list
,
1959 vars
->page_list_wired
,
1960 vars
->page_list_pal
,
1963 HIBLOG("hibernate_page_list_setall found pageCount %d\n", pageCount
);
1965 fileExtents
= (IOPolledFileExtent
*) vars
->fileExtents
->getBytesNoCopy();
1968 count
= vars
->fileExtents
->getLength() / sizeof(IOPolledFileExtent
);
1969 for (page
= 0; page
< count
; page
++)
1971 HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page
,
1972 fileExtents
[page
].start
, fileExtents
[page
].length
,
1973 fileExtents
[page
].start
+ fileExtents
[page
].length
);
1977 needEncrypt
= (0 != (kIOHibernateModeEncrypt
& gIOHibernateMode
));
1978 AbsoluteTime_to_scalar(&compTime
) = 0;
1981 clock_get_uptime(&allTime
);
1982 IOService::getPMRootDomain()->pmStatsRecordEvent(
1983 kIOPMStatsHibernateImageWrite
| kIOPMStatsEventStartFlag
, allTime
);
1988 uncompressedSize
= 0;
1990 IOPolledFileSeek(vars
->fileVars
, sizeof(IOHibernateImageHeader
));
1992 HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n",
1993 ml_get_interrupts_enabled());
1994 err
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledBeforeSleepState
, vars
->ioBuffer
);
1995 HIBLOG("IOHibernatePollerOpen(%x)\n", err
);
1996 pollerOpen
= (kIOReturnSuccess
== err
);
2000 // copy file block extent list if larger than header
2002 count
= vars
->fileExtents
->getLength();
2003 if (count
> sizeof(header
->fileExtentMap
))
2005 count
-= sizeof(header
->fileExtentMap
);
2006 err
= IOPolledFileWrite(vars
->fileVars
,
2007 ((uint8_t *) &fileExtents
[0]) + sizeof(header
->fileExtentMap
), count
, cryptvars
);
2008 if (kIOReturnSuccess
!= err
)
2012 uintptr_t hibernateBase
;
2013 uintptr_t hibernateEnd
;
2015 hibernateBase
= HIB_BASE
; /* Defined in PAL headers */
2017 hibernateEnd
= (sectHIBB
+ sectSizeHIB
);
2019 // copy out restore1 code
2022 (phys64
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
));
2025 for (pagesDone
= 0; pagesDone
< atop_32(segLen
); pagesDone
++)
2027 gIOHibernateHandoffPages
[atop_32(count
) + pagesDone
] = atop_64(phys64
) + pagesDone
;
2031 page
= atop_32(kvtophys(hibernateBase
));
2032 count
= atop_32(round_page(hibernateEnd
) - hibernateBase
);
2033 header
->restore1CodePhysPage
= page
;
2034 header
->restore1CodeVirt
= hibernateBase
;
2035 header
->restore1PageCount
= count
;
2036 header
->restore1CodeOffset
= ((uintptr_t) &hibernate_machine_entrypoint
) - hibernateBase
;
2037 header
->restore1StackOffset
= ((uintptr_t) &gIOHibernateRestoreStackEnd
[0]) - 64 - hibernateBase
;
2039 // sum __HIB sect, with zeros for the stack
2040 src
= (uint8_t *) trunc_page(hibernateBase
);
2041 for (page
= 0; page
< count
; page
++)
2043 if ((src
< &gIOHibernateRestoreStack
[0]) || (src
>= &gIOHibernateRestoreStackEnd
[0]))
2044 restore1Sum
+= hibernate_sum_page(src
, header
->restore1CodeVirt
+ page
);
2046 restore1Sum
+= 0x00000000;
2051 // write the __HIB sect, with zeros for the stack
2053 src
= (uint8_t *) trunc_page(hibernateBase
);
2054 count
= ((uintptr_t) &gIOHibernateRestoreStack
[0]) - trunc_page(hibernateBase
);
2057 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
2058 if (kIOReturnSuccess
!= err
)
2061 err
= IOPolledFileWrite(vars
->fileVars
,
2063 &gIOHibernateRestoreStackEnd
[0] - &gIOHibernateRestoreStack
[0],
2065 if (kIOReturnSuccess
!= err
)
2067 src
= &gIOHibernateRestoreStackEnd
[0];
2068 count
= round_page(hibernateEnd
) - ((uintptr_t) src
);
2071 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
2072 if (kIOReturnSuccess
!= err
)
2076 // write the preview buffer
2078 if (vars
->previewBuffer
)
2084 phys64
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
);
2085 pageAndCount
[0] = atop_64(phys64
);
2086 pageAndCount
[1] = atop_32(segLen
);
2087 err
= IOPolledFileWrite(vars
->fileVars
,
2088 (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),
2090 if (kIOReturnSuccess
!= err
)
2093 ppnum
+= sizeof(pageAndCount
);
2096 if (kIOReturnSuccess
!= err
)
2099 src
= (uint8_t *) vars
->previewBuffer
->getPhysicalSegment(0, NULL
, _kIOMemorySourceSegment
);
2100 count
= vars
->previewBuffer
->getLength();
2102 header
->previewPageListSize
= ppnum
;
2103 header
->previewSize
= count
+ ppnum
;
2105 for (page
= 0; page
< count
; page
+= page_size
)
2107 phys64
= vars
->previewBuffer
->getPhysicalSegment(page
, NULL
, kIOMemoryMapperNone
);
2108 sum1
+= hibernate_sum_page(src
+ page
, atop_64(phys64
));
2110 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
2111 if (kIOReturnSuccess
!= err
)
2115 // mark areas for no save
2118 (phys64
= vars
->ioBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
));
2121 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
2122 atop_64(phys64
), atop_32(segLen
),
2123 kIOHibernatePageStateFree
);
2124 pageCount
-= atop_32(segLen
);
2128 (phys64
= vars
->srcBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
));
2131 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
2132 atop_64(phys64
), atop_32(segLen
),
2133 kIOHibernatePageStateFree
);
2134 pageCount
-= atop_32(segLen
);
2137 // copy out bitmap of pages available for trashing during restore
2139 bitmap_size
= vars
->page_list_wired
->list_size
;
2140 src
= (uint8_t *) vars
->page_list_wired
;
2141 err
= IOPolledFileWrite(vars
->fileVars
, src
, bitmap_size
, cryptvars
);
2142 if (kIOReturnSuccess
!= err
)
2145 // mark more areas for no save, but these are not available
2146 // for trashing during restore
2148 hibernate_page_list_set_volatile(vars
->page_list
, vars
->page_list_wired
, &pageCount
);
2151 page
= atop_32(KERNEL_IMAGE_TO_PHYS(hibernateBase
));
2152 count
= atop_32(round_page(KERNEL_IMAGE_TO_PHYS(hibernateEnd
))) - page
;
2153 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
2155 kIOHibernatePageStateFree
);
2158 if (vars
->previewBuffer
) for (count
= 0;
2159 (phys64
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
));
2162 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
2163 atop_64(phys64
), atop_32(segLen
),
2164 kIOHibernatePageStateFree
);
2165 pageCount
-= atop_32(segLen
);
2169 (phys64
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
));
2172 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
2173 atop_64(phys64
), atop_32(segLen
),
2174 kIOHibernatePageStateFree
);
2175 pageCount
-= atop_32(segLen
);
2178 (void)hibernate_pal_callback
;
2180 src
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy();
2185 HIBLOG("writing %d pages\n", pageCount
);
2192 kWiredEncrypt
= kWired
| kEncrypt
,
2193 kWiredClear
= kWired
,
2194 kUnwiredEncrypt
= kEncrypt
2197 for (pageType
= kWiredEncrypt
; pageType
>= kUnwiredEncrypt
; pageType
--)
2199 if (needEncrypt
&& (kEncrypt
& pageType
))
2201 vars
->fileVars
->encryptStart
= (vars
->fileVars
->position
& ~(AES_BLOCK_SIZE
- 1));
2202 vars
->fileVars
->encryptEnd
= UINT64_MAX
;
2203 HIBLOG("encryptStart %qx\n", vars
->fileVars
->encryptStart
);
2205 if (kUnwiredEncrypt
== pageType
)
2207 // start unwired image
2208 bcopy(&cryptvars
->aes_iv
[0],
2209 &gIOHibernateCryptWakeContext
.aes_iv
[0],
2210 sizeof(cryptvars
->aes_iv
));
2211 cryptvars
= &gIOHibernateCryptWakeContext
;
2214 for (iterDone
= false, ppnum
= 0; !iterDone
; )
2216 count
= hibernate_page_list_iterate((kWired
& pageType
)
2217 ? vars
->page_list_wired
: vars
->page_list
,
2219 // kprintf("[%d](%x : %x)\n", pageType, ppnum, count);
2222 if (count
&& (kWired
& pageType
) && needEncrypt
)
2224 uint32_t checkIndex
;
2225 for (checkIndex
= 0;
2226 (checkIndex
< count
)
2227 && (((kEncrypt
& pageType
) == 0) == no_encrypt_page(ppnum
+ checkIndex
));
2240 case kWiredEncrypt
: wired_pages_encrypted
+= count
; break;
2241 case kWiredClear
: wired_pages_clear
+= count
; break;
2242 case kUnwiredEncrypt
: dirty_pages_encrypted
+= count
; break;
2245 if (iterDone
&& (kWiredEncrypt
== pageType
)) {/* not yet end of wired list */}
2248 pageAndCount
[0] = ppnum
;
2249 pageAndCount
[1] = count
;
2250 err
= IOPolledFileWrite(vars
->fileVars
,
2251 (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),
2253 if (kIOReturnSuccess
!= err
)
2257 for (page
= ppnum
; page
< (ppnum
+ count
); page
++)
2259 err
= IOMemoryDescriptorWriteFromPhysical(vars
->srcBuffer
, 0, ptoa_64(page
), page_size
);
2262 HIBLOG("IOMemoryDescriptorWriteFromPhysical %d [%ld] %x\n", __LINE__
, (long)page
, err
);
2266 sum
= hibernate_sum_page(src
, page
);
2267 if (kWired
& pageType
)
2272 clock_get_uptime(&startTime
);
2274 pageCompressedSize
= WKdm_compress ((WK_word
*) src
, (WK_word
*) (src
+ page_size
), PAGE_SIZE_IN_WORDS
);
2276 clock_get_uptime(&endTime
);
2277 ADD_ABSOLUTETIME(&compTime
, &endTime
);
2278 SUB_ABSOLUTETIME(&compTime
, &startTime
);
2279 compBytes
+= page_size
;
2281 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
2282 pageCompressedSize
= (pageCompressedSize
+ AES_BLOCK_SIZE
- 1) & ~(AES_BLOCK_SIZE
- 1);
2284 if (pageCompressedSize
> page_size
)
2286 // HIBLOG("------------lose: %d\n", pageCompressedSize);
2287 pageCompressedSize
= page_size
;
2290 if (pageCompressedSize
!= page_size
)
2291 data
= (src
+ page_size
);
2295 tag
= pageCompressedSize
| kIOHibernateTagSignature
;
2296 err
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *) &tag
, sizeof(tag
), cryptvars
);
2297 if (kIOReturnSuccess
!= err
)
2300 err
= IOPolledFileWrite(vars
->fileVars
, data
, (pageCompressedSize
+ 3) & ~3, cryptvars
);
2301 if (kIOReturnSuccess
!= err
)
2304 compressedSize
+= pageCompressedSize
;
2305 if (pageCompressedSize
)
2306 uncompressedSize
+= page_size
;
2309 if (vars
->consoleMapping
&& (0 == (1023 & pagesDone
)))
2311 blob
= ((pagesDone
* kIOHibernateProgressCount
) / pageCount
);
2312 if (blob
!= lastBlob
)
2314 ProgressUpdate(gIOHibernateGraphicsInfo
, vars
->consoleMapping
, lastBlob
, blob
);
2318 if (0 == (8191 & pagesDone
))
2320 clock_get_uptime(&endTime
);
2321 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2322 absolutetime_to_nanoseconds(endTime
, &nsec
);
2323 progressStamp
= nsec
/ 750000000ULL;
2324 if (progressStamp
!= lastProgressStamp
)
2326 lastProgressStamp
= progressStamp
;
2327 HIBPRINT("pages %d (%d%%)\n", pagesDone
, (100 * pagesDone
) / pageCount
);
2331 if (kIOReturnSuccess
!= err
)
2336 if (kIOReturnSuccess
!= err
)
2339 if ((kEncrypt
& pageType
))
2341 vars
->fileVars
->encryptEnd
= (vars
->fileVars
->position
+ AES_BLOCK_SIZE
- 1)
2342 & ~(AES_BLOCK_SIZE
- 1);
2343 HIBLOG("encryptEnd %qx\n", vars
->fileVars
->encryptEnd
);
2346 if (kWiredEncrypt
!= pageType
)
2348 // end of image1/2 - fill to next block
2349 err
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
);
2350 if (kIOReturnSuccess
!= err
)
2353 if (kWiredClear
== pageType
)
2356 header
->encryptStart
= vars
->fileVars
->encryptStart
;
2357 header
->encryptEnd
= vars
->fileVars
->encryptEnd
;
2358 image1Size
= vars
->fileVars
->position
;
2359 HIBLOG("image1Size %qd, encryptStart1 %qx, End1 %qx\n",
2360 image1Size
, header
->encryptStart
, header
->encryptEnd
);
2363 if (kIOReturnSuccess
!= err
)
2368 header
->imageSize
= vars
->fileVars
->position
;
2369 header
->image1Size
= image1Size
;
2370 header
->bitmapSize
= bitmap_size
;
2371 header
->pageCount
= pageCount
;
2373 header
->restore1Sum
= restore1Sum
;
2374 header
->image1Sum
= sum1
;
2375 header
->image2Sum
= sum2
;
2377 count
= vars
->fileExtents
->getLength();
2378 if (count
> sizeof(header
->fileExtentMap
))
2380 header
->fileExtentMapSize
= count
;
2381 count
= sizeof(header
->fileExtentMap
);
2384 header
->fileExtentMapSize
= sizeof(header
->fileExtentMap
);
2385 bcopy(&fileExtents
[0], &header
->fileExtentMap
[0], count
);
2387 header
->deviceBase
= vars
->fileVars
->block0
;
2389 IOPolledFileSeek(vars
->fileVars
, 0);
2390 err
= IOPolledFileWrite(vars
->fileVars
,
2391 (uint8_t *) header
, sizeof(IOHibernateImageHeader
),
2393 if (kIOReturnSuccess
!= err
)
2395 err
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
);
2396 if (kIOReturnSuccess
!= err
)
2398 err
= IOHibernatePollerIODone(vars
->fileVars
, true);
2399 if (kIOReturnSuccess
!= err
)
2404 clock_get_uptime(&endTime
);
2406 IOService::getPMRootDomain()->pmStatsRecordEvent(
2407 kIOPMStatsHibernateImageWrite
| kIOPMStatsEventStopFlag
, endTime
);
2409 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2410 absolutetime_to_nanoseconds(endTime
, &nsec
);
2411 HIBLOG("all time: %qd ms, ",
2414 absolutetime_to_nanoseconds(compTime
, &nsec
);
2415 HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",
2418 nsec
? (((compBytes
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0);
2420 absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
);
2421 HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s, ",
2422 vars
->fileVars
->cryptBytes
,
2424 nsec
? (((vars
->fileVars
->cryptBytes
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0);
2426 HIBLOG("\nimage %qd, uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n",
2428 uncompressedSize
, atop_32(uncompressedSize
), compressedSize
,
2429 uncompressedSize
? ((int) ((compressedSize
* 100ULL) / uncompressedSize
)) : 0,
2432 HIBLOG("wired_pages_encrypted %d, wired_pages_clear %d, dirty_pages_encrypted %d\n",
2433 wired_pages_encrypted
, wired_pages_clear
, dirty_pages_encrypted
);
2435 if (vars
->fileVars
->io
)
2436 (void) IOHibernatePollerIODone(vars
->fileVars
, false);
2439 IOHibernatePollerClose(vars
->fileVars
, kIOPolledBeforeSleepState
);
2441 if (vars
->consoleMapping
)
2442 ProgressUpdate(gIOHibernateGraphicsInfo
,
2443 vars
->consoleMapping
, 0, kIOHibernateProgressCount
);
2445 HIBLOG("hibernate_write_image done(%x)\n", err
);
2447 // should we come back via regular wake, set the state in memory.
2448 gIOHibernateState
= kIOHibernateStateInactive
;
2450 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_END
,
2451 wired_pages_encrypted
, wired_pages_clear
, dirty_pages_encrypted
, 0, 0);
2453 if (kIOReturnSuccess
== err
)
2455 if (kIOHibernateModeSleep
& gIOHibernateMode
)
2457 return (kIOHibernatePostWriteSleep
);
2459 else if(kIOHibernateModeRestart
& gIOHibernateMode
)
2461 return (kIOHibernatePostWriteRestart
);
2465 /* by default, power down */
2466 return (kIOHibernatePostWriteHalt
);
2469 else if (kIOReturnAborted
== err
)
2471 return (kIOHibernatePostWriteWake
);
2475 /* on error, sleep */
2476 return (kIOHibernatePostWriteSleep
);
2480 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2483 hibernate_machine_init(void)
2488 uint32_t pagesRead
= 0;
2489 AbsoluteTime startTime
, compTime
;
2490 AbsoluteTime allTime
, endTime
;
2493 uint32_t lastProgressStamp
= 0;
2494 uint32_t progressStamp
;
2495 uint64_t progressZeroPosition
= 0;
2496 uint32_t blob
, lastBlob
= (uint32_t) -1L;
2497 hibernate_cryptvars_t
* cryptvars
= 0;
2499 IOHibernateVars
* vars
= &gIOHibernateVars
;
2501 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
|| !vars
->fileExtents
)
2504 sum
= gIOHibernateCurrentHeader
->actualImage1Sum
;
2505 pagesDone
= gIOHibernateCurrentHeader
->actualUncompressedPages
;
2507 HIBLOG("hibernate_machine_init: state %d, image pages %d, sum was %x, image1Size %qx, conflictCount %d, nextFree %x\n",
2508 gIOHibernateState
, pagesDone
, sum
, gIOHibernateCurrentHeader
->image1Size
,
2509 gIOHibernateCurrentHeader
->conflictCount
, gIOHibernateCurrentHeader
->nextFree
);
2511 if (kIOHibernateStateWakingFromHibernate
!= gIOHibernateState
)
2513 HIBLOG("regular wake\n");
2517 HIBPRINT("diag %x %x %x %x\n",
2518 gIOHibernateCurrentHeader
->diag
[0], gIOHibernateCurrentHeader
->diag
[1],
2519 gIOHibernateCurrentHeader
->diag
[2], gIOHibernateCurrentHeader
->diag
[3]);
2521 HIBPRINT("video %x %d %d %d status %x\n",
2522 gIOHibernateGraphicsInfo
->physicalAddress
, gIOHibernateGraphicsInfo
->depth
,
2523 gIOHibernateGraphicsInfo
->width
, gIOHibernateGraphicsInfo
->height
, gIOHibernateGraphicsInfo
->gfxStatus
);
2525 if ((kIOHibernateModeDiscardCleanActive
| kIOHibernateModeDiscardCleanInactive
) & gIOHibernateMode
)
2526 hibernate_page_list_discard(vars
->page_list
);
2528 boot_args
*args
= (boot_args
*) PE_state
.bootArgs
;
2530 cryptvars
= (kIOHibernateModeEncrypt
& gIOHibernateMode
) ? &gIOHibernateCryptWakeContext
: 0;
2532 if (gIOHibernateCurrentHeader
->handoffPageCount
> gIOHibernateHandoffPageCount
)
2533 panic("handoff overflow");
2535 IOHibernateHandoff
* handoff
;
2537 bool foundCryptData
= false;
2539 for (handoff
= (IOHibernateHandoff
*) vars
->handoffBuffer
->getBytesNoCopy();
2541 handoff
= (IOHibernateHandoff
*) &handoff
->data
[handoff
->bytecount
])
2543 // HIBPRINT("handoff %p, %x, %x\n", handoff, handoff->type, handoff->bytecount);
2544 uint8_t * data
= &handoff
->data
[0];
2545 switch (handoff
->type
)
2547 case kIOHibernateHandoffTypeEnd
:
2551 case kIOHibernateHandoffTypeGraphicsInfo
:
2552 bcopy(data
, gIOHibernateGraphicsInfo
, sizeof(*gIOHibernateGraphicsInfo
));
2555 case kIOHibernateHandoffTypeCryptVars
:
2558 hibernate_cryptwakevars_t
*
2559 wakevars
= (hibernate_cryptwakevars_t
*) &handoff
->data
[0];
2560 bcopy(&wakevars
->aes_iv
[0], &cryptvars
->aes_iv
[0], sizeof(cryptvars
->aes_iv
));
2562 foundCryptData
= true;
2563 bzero(data
, handoff
->bytecount
);
2566 case kIOHibernateHandoffTypeMemoryMap
:
2567 hibernate_newruntime_map(data
, handoff
->bytecount
,
2568 gIOHibernateCurrentHeader
->systemTableOffset
);
2571 case kIOHibernateHandoffTypeDeviceTree
:
2573 // DTEntry chosen = NULL;
2574 // HIBPRINT("DTLookupEntry %d\n", DTLookupEntry((const DTEntry) data, "/chosen", &chosen));
2579 done
= (kIOHibernateHandoffType
!= (handoff
->type
& 0xFFFF0000));
2583 if (cryptvars
&& !foundCryptData
)
2584 panic("hibernate handoff");
2586 if (vars
->videoMapping
2587 && gIOHibernateGraphicsInfo
->physicalAddress
2588 && (args
->Video
.v_baseAddr
== gIOHibernateGraphicsInfo
->physicalAddress
))
2590 vars
->videoMapSize
= round_page(gIOHibernateGraphicsInfo
->height
2591 * gIOHibernateGraphicsInfo
->rowBytes
);
2592 IOMapPages(kernel_map
,
2593 vars
->videoMapping
, gIOHibernateGraphicsInfo
->physicalAddress
,
2594 vars
->videoMapSize
, kIOMapInhibitCache
);
2597 uint8_t * src
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy();
2598 uint32_t decoOffset
;
2600 clock_get_uptime(&allTime
);
2601 AbsoluteTime_to_scalar(&compTime
) = 0;
2604 HIBLOG("IOHibernatePollerOpen(), ml_get_interrupts_enabled %d\n", ml_get_interrupts_enabled());
2605 err
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledAfterSleepState
, 0);
2606 HIBLOG("IOHibernatePollerOpen(%x)\n", err
);
2608 if (gIOHibernateCurrentHeader
->previewSize
)
2609 progressZeroPosition
= gIOHibernateCurrentHeader
->previewSize
2610 + gIOHibernateCurrentHeader
->fileExtentMapSize
2611 - sizeof(gIOHibernateCurrentHeader
->fileExtentMap
)
2612 + ptoa_64(gIOHibernateCurrentHeader
->restore1PageCount
);
2614 IOPolledFileSeek(vars
->fileVars
, gIOHibernateCurrentHeader
->image1Size
);
2616 if (vars
->videoMapSize
)
2618 lastBlob
= ((vars
->fileVars
->position
- progressZeroPosition
) * kIOHibernateProgressCount
)
2619 / (gIOHibernateCurrentHeader
->imageSize
- progressZeroPosition
);
2620 ProgressUpdate(gIOHibernateGraphicsInfo
, (uint8_t *) vars
->videoMapping
, 0, lastBlob
);
2623 // kick off the read ahead
2624 vars
->fileVars
->io
= false;
2625 vars
->fileVars
->bufferHalf
= 0;
2626 vars
->fileVars
->bufferLimit
= 0;
2627 vars
->fileVars
->lastRead
= 0;
2628 vars
->fileVars
->readEnd
= gIOHibernateCurrentHeader
->imageSize
;
2629 vars
->fileVars
->bufferOffset
= vars
->fileVars
->bufferLimit
;
2630 vars
->fileVars
->cryptBytes
= 0;
2631 AbsoluteTime_to_scalar(&vars
->fileVars
->cryptTime
) = 0;
2633 err
= IOPolledFileRead(vars
->fileVars
, 0, 0, cryptvars
);
2634 vars
->fileVars
->bufferOffset
= vars
->fileVars
->bufferLimit
;
2637 HIBLOG("hibernate_machine_init reading\n");
2639 uint32_t * header
= (uint32_t *) src
;
2642 while (kIOReturnSuccess
== err
)
2647 vm_offset_t ppnum
, compressedSize
;
2649 err
= IOPolledFileRead(vars
->fileVars
, src
, 8, cryptvars
);
2650 if (kIOReturnSuccess
!= err
)
2656 // HIBPRINT("(%x, %x)\n", ppnum, count);
2661 for (page
= 0; page
< count
; page
++)
2663 err
= IOPolledFileRead(vars
->fileVars
, (uint8_t *) &tag
, 4, cryptvars
);
2664 if (kIOReturnSuccess
!= err
)
2667 compressedSize
= kIOHibernateTagLength
& tag
;
2668 if (kIOHibernateTagSignature
!= (tag
& ~kIOHibernateTagLength
))
2670 err
= kIOReturnIPCError
;
2674 if (!compressedSize
)
2681 err
= IOPolledFileRead(vars
->fileVars
, src
, (compressedSize
+ 3) & ~3, cryptvars
);
2682 if (kIOReturnSuccess
!= err
)
2685 if (compressedSize
< page_size
)
2687 decoOffset
= page_size
;
2689 clock_get_uptime(&startTime
);
2690 WKdm_decompress((WK_word
*) src
, (WK_word
*) (src
+ decoOffset
), PAGE_SIZE_IN_WORDS
);
2691 clock_get_uptime(&endTime
);
2692 ADD_ABSOLUTETIME(&compTime
, &endTime
);
2693 SUB_ABSOLUTETIME(&compTime
, &startTime
);
2695 compBytes
+= page_size
;
2700 sum
+= hibernate_sum_page((src
+ decoOffset
), ppnum
);
2702 err
= IOMemoryDescriptorReadToPhysical(vars
->srcBuffer
, decoOffset
, ptoa_64(ppnum
), page_size
);
2705 HIBLOG("IOMemoryDescriptorReadToPhysical [%ld] %x\n", (long)ppnum
, err
);
2713 if (vars
->videoMapSize
&& (0 == (1023 & pagesDone
)))
2715 blob
= ((vars
->fileVars
->position
- progressZeroPosition
) * kIOHibernateProgressCount
)
2716 / (gIOHibernateCurrentHeader
->imageSize
- progressZeroPosition
);
2717 if (blob
!= lastBlob
)
2719 ProgressUpdate(gIOHibernateGraphicsInfo
, (uint8_t *) vars
->videoMapping
, lastBlob
, blob
);
2724 if (0 == (8191 & pagesDone
))
2726 clock_get_uptime(&endTime
);
2727 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2728 absolutetime_to_nanoseconds(endTime
, &nsec
);
2729 progressStamp
= nsec
/ 750000000ULL;
2730 if (progressStamp
!= lastProgressStamp
)
2732 lastProgressStamp
= progressStamp
;
2733 HIBPRINT("pages %d (%d%%)\n", pagesDone
,
2734 (100 * pagesDone
) / gIOHibernateCurrentHeader
->pageCount
);
2739 if (pagesDone
== gIOHibernateCurrentHeader
->actualUncompressedPages
)
2740 err
= kIOReturnLockedRead
;
2742 if (kIOReturnSuccess
!= err
)
2743 panic("Hibernate restore error %x", err
);
2745 gIOHibernateCurrentHeader
->actualImage2Sum
= sum
;
2747 if (vars
->fileVars
->io
)
2748 (void) IOHibernatePollerIODone(vars
->fileVars
, false);
2750 err
= IOHibernatePollerClose(vars
->fileVars
, kIOPolledAfterSleepState
);
2752 if (vars
->videoMapSize
)
2753 ProgressUpdate(gIOHibernateGraphicsInfo
,
2754 (uint8_t *) vars
->videoMapping
, 0, kIOHibernateProgressCount
);
2756 clock_get_uptime(&endTime
);
2758 IOService::getPMRootDomain()->pmStatsRecordEvent(
2759 kIOPMStatsHibernateImageRead
| kIOPMStatsEventStartFlag
, allTime
);
2760 IOService::getPMRootDomain()->pmStatsRecordEvent(
2761 kIOPMStatsHibernateImageRead
| kIOPMStatsEventStopFlag
, endTime
);
2763 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2764 absolutetime_to_nanoseconds(endTime
, &nsec
);
2766 HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %qd ms, ",
2767 pagesDone
, sum
, nsec
/ 1000000ULL);
2769 absolutetime_to_nanoseconds(compTime
, &nsec
);
2770 HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",
2773 nsec
? (((compBytes
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0);
2775 absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
);
2776 HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s\n",
2777 vars
->fileVars
->cryptBytes
,
2779 nsec
? (((vars
->fileVars
->cryptBytes
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0);
2781 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 2) | DBG_FUNC_NONE
, pagesRead
, pagesDone
, 0, 0, 0);
2784 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */