2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
36 - PMRootDomain calls IOHibernateSystemSleep() before system sleep
37 (devices awake, normal execution context)
38 - IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level,
39 grabs its extents and searches for a polling driver willing to work with that IOMedia.
40 The BSD code makes an ioctl to the storage driver to get the partition base offset to
41 the disk, and other ioctls to get the transfer constraints
42 If successful, the file is written to make sure its initially not bootable (in case of
43 later failure) and nvram set to point to the first block of the file. (Has to be done
44 here so blocking is possible in nvram support).
45 hibernate_setup() in osfmk is called to allocate page bitmaps for all dram, and
46 page out any pages it wants to (currently zero, but probably some percentage of memory).
47 Its assumed just allocating pages will cause the VM system to naturally select the best
48 pages for eviction. It also copies processor flags needed for the restore path and sets
49 a flag in the boot processor proc info.
50 gIOHibernateState = kIOHibernateStateHibernating.
51 - Regular sleep progresses - some drivers may inspect the root domain property
52 kIOHibernateStateKey to modify behavior. The platform driver saves state to memory
53 as usual but leaves motherboard I/O on.
54 - Eventually the platform calls ml_ppc_sleep() in the shutdown context on the last cpu,
55 at which point memory is ready to be saved. mapping_hibernate_flush() is called to get
56 all ppc RC bits out of the hash table and caches into the mapping structures.
57 - hibernate_write_image() is called (still in shutdown context, no blocking or preemption).
58 hibernate_page_list_setall() is called to get a bitmap of dram pages that need to be saved.
59 All pages are assumed to be saved (as part of the wired image) unless explicitly subtracted
60 by hibernate_page_list_setall(), avoiding having to find arch dependent low level bits.
61 The image header and block list are written. The header includes the second file extent so
62 only the header block is needed to read the file, regardless of filesystem.
63 The kernel section "__HIB" is written uncompressed to the image. This section of code and data
64 (only) is used to decompress the image during wake/boot.
65 Some additional pages are removed from the bitmaps - the buffers used for hibernation.
66 The bitmaps are written to the image.
67 More areas are removed from the bitmaps (after they have been written to the image) - the
68 section "__HIB" pages and interrupt stack.
69 Each wired page is compressed and written and then each non-wired page. Compression and
70 disk writes are in parallel.
71 The image header is written to the start of the file and the polling driver closed.
72 The machine powers down (or sleeps).
76 - BootX sees the boot-image nvram variable containing the device and block number of the image,
77 reads the header and if the signature is correct proceeds. The boot-image variable is cleared.
78 - BootX reads the portion of the image used for wired pages, to memory. Its assumed this will fit
79 in the OF memory environment, and the image is decrypted. There is no decompression in BootX,
80 that is in the kernel's __HIB section.
81 - BootX copies the "__HIB" section to its correct position in memory, quiesces and calls its entry
82 hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off,
83 only code & data in that section is safe to call since all the other wired pages are still
84 compressed in the image.
85 - hibernate_kernel_entrypoint() removes pages occupied by the raw image from the page bitmaps.
86 It uses the bitmaps to work out which pages can be uncompressed from the image to their final
87 location directly, and copies those that can't to interim free pages. When the image has been
88 completed, the copies are uncompressed, overwriting the wired image pages.
89 hibernate_restore_phys_page() (in osfmk since its arch dependent, but part of the "__HIB" section)
90 is used to get pages into place for 64bit.
91 - the reset vector is called (at least on ppc), the kernel proceeds on a normal wake, with some
92 changes conditional on the per proc flag - before VM is turned on the boot cpu, all mappings
93 are removed from the software strutures, and the hash table is reinitialized.
94 - After the platform CPU init code is called, hibernate_machine_init() is called to restore the rest
95 of memory, using the polled mode driver, before other threads can run or any devices are turned on.
96 This reduces the memory usage for BootX and allows decompression in parallel with disk reads,
97 for the remaining non wired pages.
98 - The polling driver is closed down and regular wake proceeds. When the kernel calls iokit to wake
99 (normal execution context) hibernate_teardown() in osmfk is called to release any memory, the file
104 IOHibernateSystemSleep() finds a polled mode interface to the ATA controller via a property in the
105 registry, specifying an object of calls IOPolledInterface.
107 Before the system goes to sleep it searches from the IOMedia object (could be a filesystem or
108 partition) that the image is going to live, looking for polled interface properties. If it finds
109 one the IOMedia object is passed to a "probe" call for the interface to accept or reject. All the
110 interfaces found are kept in an ordered list.
112 There is an Open/Close pair of calls made to each of the interfaces at various stages since there are
113 few different contexts things happen in:
115 - there is an Open/Close (Preflight) made before any part of the system has slept (I/O is all
116 up and running) and after wake - this is safe to allocate memory and do anything. The device
117 ignores sleep requests from that point since its a waste of time if it goes to sleep and
118 immediately wakes back up for the image write.
120 - there is an Open/Close (BeforeSleep) pair made around the image write operations that happen
121 immediately before sleep. These can't block or allocate memory - the I/O system is asleep apart
122 from the low level bits (motherboard I/O etc). There is only one thread running. The close can be
123 used to flush and set the disk to sleep.
125 - there is an Open/Close (AfterSleep) pair made around the image read operations that happen
126 immediately after sleep. These can't block or allocate memory. This is happening after the platform
127 expert has woken the low level bits of the system, but most of the I/O system has not. There is only
130 For the actual I/O, all the ops are with respect to a single IOMemoryDescriptor that was passed
131 (prepared) to the Preflight Open() call. There is a read/write op, buffer offset to the IOMD for
132 the data, an offset to the disk and length (block aligned 64 bit numbers), and completion callback.
133 Each I/O is async but only one is ever outstanding. The polled interface has a checkForWork call
134 that is called for the hardware to check for events, and complete the I/O via the callback.
135 The hibernate path uses the same transfer constraints the regular cluster I/O path in BSD uses
139 #include <sys/systm.h>
141 #include <IOKit/IOWorkLoop.h>
142 #include <IOKit/IOCommandGate.h>
143 #include <IOKit/IOTimerEventSource.h>
144 #include <IOKit/IOPlatformExpert.h>
145 #include <IOKit/IOKitDebug.h>
146 #include <IOKit/IOTimeStamp.h>
147 #include <IOKit/pwr_mgt/RootDomain.h>
148 #include <IOKit/pwr_mgt/IOPMPrivate.h>
149 #include <IOKit/IOMessage.h>
150 #include <IOKit/IODeviceTreeSupport.h>
151 #include <IOKit/IOBSD.h>
152 #include "RootDomainUserClient.h"
153 #include <IOKit/pwr_mgt/IOPowerConnection.h>
154 #include "IOPMPowerStateQueue.h"
155 #include <IOKit/IOBufferMemoryDescriptor.h>
156 #include <crypto/aes.h>
159 #include <sys/conf.h>
160 #include <sys/stat.h>
161 #include <sys/fcntl.h> // (FWRITE, ...)
162 #include <sys/sysctl.h>
164 #include <IOKit/IOHibernatePrivate.h>
165 #include <IOKit/IOPolledInterface.h>
166 #include <IOKit/IONVRAM.h>
167 #include "IOHibernateInternal.h"
169 #include "IOKitKernelInternal.h"
171 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
173 OSDefineMetaClassAndAbstractStructors(IOPolledInterface
, OSObject
);
175 OSMetaClassDefineReservedUnused(IOPolledInterface
, 0);
176 OSMetaClassDefineReservedUnused(IOPolledInterface
, 1);
177 OSMetaClassDefineReservedUnused(IOPolledInterface
, 2);
178 OSMetaClassDefineReservedUnused(IOPolledInterface
, 3);
179 OSMetaClassDefineReservedUnused(IOPolledInterface
, 4);
180 OSMetaClassDefineReservedUnused(IOPolledInterface
, 5);
181 OSMetaClassDefineReservedUnused(IOPolledInterface
, 6);
182 OSMetaClassDefineReservedUnused(IOPolledInterface
, 7);
183 OSMetaClassDefineReservedUnused(IOPolledInterface
, 8);
184 OSMetaClassDefineReservedUnused(IOPolledInterface
, 9);
185 OSMetaClassDefineReservedUnused(IOPolledInterface
, 10);
186 OSMetaClassDefineReservedUnused(IOPolledInterface
, 11);
187 OSMetaClassDefineReservedUnused(IOPolledInterface
, 12);
188 OSMetaClassDefineReservedUnused(IOPolledInterface
, 13);
189 OSMetaClassDefineReservedUnused(IOPolledInterface
, 14);
190 OSMetaClassDefineReservedUnused(IOPolledInterface
, 15);
192 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
194 extern uint32_t gIOHibernateState
;
195 uint32_t gIOHibernateMode
;
196 static char gIOHibernateBootSignature
[256+1];
197 static char gIOHibernateFilename
[MAXPATHLEN
+1];
198 static uint32_t gIOHibernateFreeRatio
= 0; // free page target (percent)
199 uint32_t gIOHibernateFreeTime
= 0*1000; // max time to spend freeing pages (ms)
201 static IODTNVRAM
* gIOOptionsEntry
;
202 static IORegistryEntry
* gIOChosenEntry
;
204 static const OSSymbol
* gIOCreateEFIDevicePathSymbol
;
207 static IOPolledFileIOVars gFileVars
;
208 static IOHibernateVars gIOHibernateVars
;
209 static struct kern_direct_file_io_ref_t
* gIOHibernateFileRef
;
210 static hibernate_cryptvars_t gIOHibernateCryptWakeContext
;
212 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
214 enum { kXPRamAudioVolume
= 8 };
215 enum { kDefaultIOSize
= 128 * 1024 };
216 enum { kVideoMapSize
= 32 * 1024 * 1024 };
218 #ifndef kIOMediaPreferredBlockSizeKey
219 #define kIOMediaPreferredBlockSizeKey "Preferred Block Size"
222 #ifndef kIOBootPathKey
223 #define kIOBootPathKey "bootpath"
225 #ifndef kIOSelectedBootDeviceKey
226 #define kIOSelectedBootDeviceKey "boot-device"
230 enum { kIOHibernateMinPollersNeeded
= 2 };
232 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
234 // copy from phys addr to MD
237 IOMemoryDescriptorWriteFromPhysical(IOMemoryDescriptor
* md
,
238 IOByteCount offset
, addr64_t bytes
, IOByteCount length
)
240 addr64_t srcAddr
= bytes
;
241 IOByteCount remaining
;
243 remaining
= length
= min(length
, md
->getLength() - offset
);
244 while (remaining
) { // (process another target segment?)
248 dstAddr64
= md
->getPhysicalSegment64(offset
, &dstLen
);
252 // Clip segment length to remaining
253 if (dstLen
> remaining
)
257 bcopy_phys(srcAddr
, dstAddr64
, dstLen
);
259 copypv(srcAddr
, dstAddr64
, dstLen
,
260 cppvPsnk
| cppvFsnk
| cppvNoRefSrc
| cppvNoModSnk
| cppvKmap
);
269 return remaining
? kIOReturnUnderrun
: kIOReturnSuccess
;
272 // copy from MD to phys addr
275 IOMemoryDescriptorReadToPhysical(IOMemoryDescriptor
* md
,
276 IOByteCount offset
, addr64_t bytes
, IOByteCount length
)
278 addr64_t dstAddr
= bytes
;
279 IOByteCount remaining
;
281 remaining
= length
= min(length
, md
->getLength() - offset
);
282 while (remaining
) { // (process another target segment?)
286 srcAddr64
= md
->getPhysicalSegment64(offset
, &dstLen
);
290 // Clip segment length to remaining
291 if (dstLen
> remaining
)
295 bcopy_phys(srcAddr64
, dstAddr
, dstLen
);
297 copypv(srcAddr
, dstAddr64
, dstLen
,
298 cppvPsnk
| cppvFsnk
| cppvNoRefSrc
| cppvNoModSnk
| cppvKmap
);
307 return remaining
? kIOReturnUnderrun
: kIOReturnSuccess
;
310 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
313 hibernate_set_page_state(hibernate_page_list_t
* page_list
, hibernate_page_list_t
* page_list_wired
,
314 vm_offset_t ppnum
, vm_offset_t count
, uint32_t kind
)
319 case kIOHibernatePageStateUnwiredSave
:
321 for (; ppnum
< count
; ppnum
++)
323 hibernate_page_bitset(page_list
, FALSE
, ppnum
);
324 hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
);
327 case kIOHibernatePageStateWiredSave
:
329 for (; ppnum
< count
; ppnum
++)
331 hibernate_page_bitset(page_list
, FALSE
, ppnum
);
332 hibernate_page_bitset(page_list_wired
, FALSE
, ppnum
);
335 case kIOHibernatePageStateFree
:
337 for (; ppnum
< count
; ppnum
++)
339 hibernate_page_bitset(page_list
, TRUE
, ppnum
);
340 hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
);
344 panic("hibernate_set_page_state");
349 hibernate_page_list_iterate(hibernate_page_list_t
* list
, vm_offset_t
* pPage
)
351 uint32_t page
= *pPage
;
353 hibernate_bitmap_t
* bitmap
;
355 while ((bitmap
= hibernate_page_bitmap_pin(list
, &page
)))
357 count
= hibernate_page_bitmap_count(bitmap
, TRUE
, page
);
361 if (page
<= bitmap
->last_page
)
367 count
= hibernate_page_bitmap_count(bitmap
, FALSE
, page
);
374 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
377 IOHibernatePollerProbe(IOPolledFileIOVars
* vars
, IOService
* target
)
379 IOReturn err
= kIOReturnError
;
381 IOPolledInterface
* poller
;
383 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
385 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
386 err
= poller
->probe(target
);
389 HIBLOG("IOPolledInterface::probe[%d] 0x%x\n", idx
, err
);
398 IOHibernatePollerOpen(IOPolledFileIOVars
* vars
, uint32_t state
, IOMemoryDescriptor
* md
)
400 IOReturn err
= kIOReturnError
;
402 IOPolledInterface
* poller
;
404 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
406 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
407 err
= poller
->open(state
, md
);
410 HIBLOG("IOPolledInterface::open[%d] 0x%x\n", idx
, err
);
419 IOHibernatePollerClose(IOPolledFileIOVars
* vars
, uint32_t state
)
421 IOReturn err
= kIOReturnError
;
423 IOPolledInterface
* poller
;
426 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
429 err
= poller
->close(state
);
431 HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx
, err
);
438 IOHibernatePollerIOComplete(void * target
,
441 UInt64 actualByteCount
)
443 IOPolledFileIOVars
* vars
= (IOPolledFileIOVars
*) parameter
;
445 vars
->ioStatus
= status
;
449 IOHibernatePollerIO(IOPolledFileIOVars
* vars
,
450 uint32_t operation
, uint32_t bufferOffset
,
451 uint64_t deviceOffset
, uint64_t length
)
454 IOReturn err
= kIOReturnError
;
455 IOPolledInterface
* poller
;
456 IOPolledCompletion completion
;
458 completion
.target
= 0;
459 completion
.action
= &IOHibernatePollerIOComplete
;
460 completion
.parameter
= vars
;
464 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(0);
465 err
= poller
->startIO(operation
, bufferOffset
, deviceOffset
+ vars
->block0
, length
, completion
);
467 HIBLOG("IOPolledInterface::startIO[%d] 0x%x\n", 0, err
);
473 IOHibernatePollerIODone(IOPolledFileIOVars
* vars
)
475 IOReturn err
= kIOReturnError
;
477 IOPolledInterface
* poller
;
479 while (-1 == vars
->ioStatus
)
482 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
485 err
= poller
->checkForWork();
487 HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx
, err
);
491 if (kIOReturnSuccess
!= vars
->ioStatus
)
492 HIBLOG("IOPolledInterface::ioStatus 0x%x\n", vars
->ioStatus
);
494 return (vars
->ioStatus
);
498 IOPolledInterface::checkAllForWork(void)
500 IOReturn err
= kIOReturnNotReady
;
502 IOPolledInterface
* poller
;
504 IOHibernateVars
* vars
= &gIOHibernateVars
;
506 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
)
510 (poller
= (IOPolledInterface
*) vars
->fileVars
->pollers
->getObject(idx
));
513 err
= poller
->checkForWork();
515 HIBLOG("IOPolledInterface::checkAllForWork[%d] 0x%x\n", idx
, err
);
521 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
523 struct _OpenFileContext
530 file_extent_callback(void * ref
, uint64_t start
, uint64_t length
)
532 _OpenFileContext
* ctx
= (_OpenFileContext
*) ref
;
533 IOPolledFileExtent extent
;
535 extent
.start
= start
;
536 extent
.length
= length
;
538 ctx
->extents
->appendBytes(&extent
, sizeof(extent
));
543 IOPolledFileOpen( const char * filename
, IOBufferMemoryDescriptor
* ioBuffer
,
544 IOPolledFileIOVars
** fileVars
, OSData
** fileExtents
,
547 IOReturn err
= kIOReturnError
;
548 IOPolledFileIOVars
* vars
;
549 _OpenFileContext ctx
;
550 OSData
* extentsData
;
552 IORegistryEntry
* part
= 0;
553 OSDictionary
* matching
;
555 dev_t hibernate_image_dev
;
561 HIBLOG("sizeof(IOHibernateImageHeader) == %ld\n", sizeof(IOHibernateImageHeader
));
562 if (sizeof(IOHibernateImageHeader
) != 512)
566 vars
->buffer
= (uint8_t *) ioBuffer
->getBytesNoCopy();
567 vars
->bufferHalf
= 0;
568 vars
->bufferOffset
= 0;
569 vars
->bufferSize
= ioBuffer
->getLength() >> 1;
571 extentsData
= OSData::withCapacity(32);
573 ctx
.extents
= extentsData
;
575 vars
->fileRef
= kern_open_file_for_direct_io(filename
,
576 &file_extent_callback
, &ctx
,
577 &hibernate_image_dev
,
582 err
= kIOReturnNoSpace
;
585 HIBLOG("Opened file %s, size %qd, partition base 0x%qx, maxio %qx\n", filename
, ctx
.size
,
586 vars
->block0
, maxiobytes
);
587 if (ctx
.size
< 1*1024*1024) // check against image size estimate!
589 err
= kIOReturnNoSpace
;
593 if (maxiobytes
< vars
->bufferSize
)
594 vars
->bufferSize
= maxiobytes
;
596 vars
->extentMap
= (IOPolledFileExtent
*) extentsData
->getBytesNoCopy();
598 matching
= IOService::serviceMatching("IOMedia");
599 num
= OSNumber::withNumber(major(hibernate_image_dev
), 32);
600 matching
->setObject(kIOBSDMajorKey
, num
);
602 num
= OSNumber::withNumber(minor(hibernate_image_dev
), 32);
603 matching
->setObject(kIOBSDMinorKey
, num
);
605 iter
= IOService::getMatchingServices(matching
);
609 part
= (IORegistryEntry
*) iter
->getNextObject();
615 IORegistryEntry
* next
;
616 IORegistryEntry
* child
;
619 num
= (OSNumber
*) part
->getProperty(kIOBSDMajorKey
);
622 major
= num
->unsigned32BitValue();
623 num
= (OSNumber
*) part
->getProperty(kIOBSDMinorKey
);
626 minor
= num
->unsigned32BitValue();
628 hibernate_image_dev
= makedev(major
, minor
);
630 vars
->pollers
= OSArray::withCapacity(4);
634 vars
->blockSize
= 512;
638 IOPolledInterface
* poller
;
641 obj
= next
->getProperty(kIOPolledInterfaceSupportKey
);
642 if (kOSBooleanFalse
== obj
)
644 vars
->pollers
->flushCollection();
647 else if ((poller
= OSDynamicCast(IOPolledInterface
, obj
)))
648 vars
->pollers
->setObject(poller
);
649 if ((num
= OSDynamicCast(OSNumber
, next
->getProperty(kIOMediaPreferredBlockSizeKey
))))
650 vars
->blockSize
= num
->unsigned32BitValue();
653 while ((next
= child
->getParentEntry(gIOServicePlane
))
654 && child
->isParent(next
, gIOServicePlane
, true));
656 HIBLOG("hibernate image major %d, minor %d, blocksize %ld, pollers %d\n",
657 major
, minor
, vars
->blockSize
, vars
->pollers
->getCount());
658 if (vars
->pollers
->getCount() < kIOHibernateMinPollersNeeded
)
661 err
= IOHibernatePollerProbe(vars
, (IOService
*) part
);
662 if (kIOReturnSuccess
!= err
)
665 err
= IOHibernatePollerOpen(vars
, kIOPolledPreflightState
, ioBuffer
);
666 if (kIOReturnSuccess
!= err
)
670 *fileExtents
= extentsData
;
674 if ((extentsData
->getLength() >= sizeof(IOPolledFileExtent
)))
679 if (!gIOCreateEFIDevicePathSymbol
)
680 gIOCreateEFIDevicePathSymbol
= OSSymbol::withCString("CreateEFIDevicePath");
682 sprintf(str2
, "%qx", vars
->extentMap
[0]);
684 err
= IOService::getPlatform()->callPlatformFunction(
685 gIOCreateEFIDevicePathSymbol
, false,
686 (void *) part
, (void *) str2
, (void *) true,
690 int len
= sizeof(str1
);
692 if (!part
->getPath(str1
, &len
, gIODTPlane
))
693 err
= kIOReturnNotFound
;
696 sprintf(str2
, ",%qx", vars
->extentMap
[0]);
697 // (strip the plane name)
698 char * tail
= strchr(str1
, ':');
701 data
= OSData::withBytes(tail
+ 1, strlen(tail
+ 1));
702 data
->appendBytes(str2
, strlen(str2
));
705 if (kIOReturnSuccess
== err
)
708 HIBLOG("error 0x%x getting path\n", err
);
713 if (kIOReturnSuccess
!= err
)
715 HIBLOG("error 0x%x opening hibernation file\n", err
);
717 kern_close_file_for_direct_io(vars
->fileRef
);
727 IOPolledFileClose( IOPolledFileIOVars
* vars
)
731 IOHibernatePollerClose(vars
, kIOPolledPostflightState
);
732 vars
->pollers
->release();
735 gIOHibernateFileRef
= vars
->fileRef
;
737 bzero(vars
, sizeof(IOPolledFileIOVars
));
739 return (kIOReturnSuccess
);
743 IOPolledFileSeek(IOPolledFileIOVars
* vars
, uint64_t position
)
745 IOPolledFileExtent
* extentMap
;
747 extentMap
= vars
->extentMap
;
749 vars
->position
= position
;
751 while (position
>= extentMap
->length
)
753 position
-= extentMap
->length
;
757 vars
->currentExtent
= extentMap
;
758 vars
->extentRemaining
= extentMap
->length
- position
;
759 vars
->extentPosition
= vars
->position
- position
;
761 if (vars
->bufferSize
<= vars
->extentRemaining
)
762 vars
->bufferLimit
= vars
->bufferSize
;
764 vars
->bufferLimit
= vars
->extentRemaining
;
766 return (kIOReturnSuccess
);
770 IOPolledFileWrite(IOPolledFileIOVars
* vars
,
771 const uint8_t * bytes
, IOByteCount size
,
772 hibernate_cryptvars_t
* cryptvars
)
774 IOReturn err
= kIOReturnSuccess
;
782 // seek to end of block & flush
783 size
= vars
->position
& (vars
->blockSize
- 1);
785 size
= vars
->blockSize
- size
;
787 // use some garbage for the fill
788 bytes
= vars
->buffer
+ vars
->bufferOffset
;
791 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
799 bcopy(bytes
, vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
803 bzero(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
806 vars
->bufferOffset
+= copy
;
807 vars
->position
+= copy
;
809 if (flush
&& vars
->bufferOffset
)
811 uint64_t offset
= (vars
->position
- vars
->bufferOffset
812 - vars
->extentPosition
+ vars
->currentExtent
->start
);
813 uint32_t length
= (vars
->bufferOffset
);
815 if (cryptvars
&& vars
->encryptStart
&& (vars
->position
> vars
->encryptStart
))
817 uint32_t encryptLen
, encryptStart
;
818 encryptLen
= vars
->position
- vars
->encryptStart
;
819 if (encryptLen
> length
)
821 encryptStart
= length
- encryptLen
;
823 // encrypt the buffer
824 aes_encrypt_cbc(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
825 &cryptvars
->aes_iv
[0],
826 encryptLen
/ AES_BLOCK_SIZE
,
827 vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
828 &cryptvars
->ctx
.encrypt
);
829 // save initial vector for following encrypts
830 bcopy(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
+ encryptLen
- AES_BLOCK_SIZE
,
831 &cryptvars
->aes_iv
[0],
837 err
= IOHibernatePollerIODone(vars
);
838 if (kIOReturnSuccess
!= err
)
842 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
843 //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length);
845 err
= IOHibernatePollerIO(vars
, kIOPolledWrite
, vars
->bufferHalf
, offset
, length
);
846 if (kIOReturnSuccess
!= err
)
850 vars
->extentRemaining
-= vars
->bufferOffset
;
851 if (!vars
->extentRemaining
)
853 vars
->currentExtent
++;
854 vars
->extentRemaining
= vars
->currentExtent
->length
;
855 vars
->extentPosition
= vars
->position
;
856 if (!vars
->extentRemaining
)
858 err
= kIOReturnOverrun
;
863 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
864 vars
->bufferOffset
= 0;
865 if (vars
->bufferSize
<= vars
->extentRemaining
)
866 vars
->bufferLimit
= vars
->bufferSize
;
868 vars
->bufferLimit
= vars
->extentRemaining
;
879 IOPolledFileRead(IOPolledFileIOVars
* vars
,
880 uint8_t * bytes
, IOByteCount size
,
881 hibernate_cryptvars_t
* cryptvars
)
883 IOReturn err
= kIOReturnSuccess
;
886 // bytesWritten += size;
890 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
896 bcopy(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, bytes
, copy
);
900 vars
->bufferOffset
+= copy
;
901 // vars->position += copy;
903 if (vars
->bufferOffset
== vars
->bufferLimit
)
907 err
= IOHibernatePollerIODone(vars
);
908 if (kIOReturnSuccess
!= err
)
914 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
916 vars
->position
+= vars
->lastRead
;
917 vars
->extentRemaining
-= vars
->lastRead
;
918 vars
->bufferLimit
= vars
->lastRead
;
920 if (!vars
->extentRemaining
)
922 vars
->currentExtent
++;
923 vars
->extentRemaining
= vars
->currentExtent
->length
;
924 vars
->extentPosition
= vars
->position
;
925 if (!vars
->extentRemaining
)
927 err
= kIOReturnOverrun
;
932 if (vars
->extentRemaining
<= vars
->bufferSize
)
933 vars
->lastRead
= vars
->extentRemaining
;
935 vars
->lastRead
= vars
->bufferSize
;
937 uint64_t offset
= (vars
->position
938 - vars
->extentPosition
+ vars
->currentExtent
->start
);
939 uint64_t length
= (vars
->lastRead
);
941 //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length);
943 err
= IOHibernatePollerIO(vars
, kIOPolledRead
, vars
->bufferHalf
, offset
, length
);
944 if (kIOReturnSuccess
!= err
)
948 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
949 vars
->bufferOffset
= 0;
953 uint8_t thisVector
[AES_BLOCK_SIZE
];
954 // save initial vector for following decrypts
955 bcopy(&cryptvars
->aes_iv
[0], &thisVector
[0], AES_BLOCK_SIZE
);
956 bcopy(vars
->buffer
+ vars
->bufferHalf
+ vars
->lastRead
- AES_BLOCK_SIZE
,
957 &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
);
958 // decrypt the buffer
959 aes_decrypt_cbc(vars
->buffer
+ vars
->bufferHalf
,
961 vars
->lastRead
/ AES_BLOCK_SIZE
,
962 vars
->buffer
+ vars
->bufferHalf
,
963 &cryptvars
->ctx
.decrypt
);
972 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
975 IOHibernateSystemSleep(void)
983 IOHibernateVars
* vars
= &gIOHibernateVars
;
985 if (vars
->fileVars
&& vars
->fileVars
->fileRef
)
986 // already on the way down
987 return (kIOReturnSuccess
);
989 gIOHibernateState
= kIOHibernateStateInactive
;
991 if ((obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernateModeKey
)))
993 if ((num
= OSDynamicCast(OSNumber
, obj
)))
994 gIOHibernateMode
= num
->unsigned32BitValue();
995 if (kIOHibernateModeSleep
& gIOHibernateMode
)
996 // default to discard clean for safe sleep
997 gIOHibernateMode
^= (kIOHibernateModeDiscardCleanInactive
998 | kIOHibernateModeDiscardCleanActive
);
1002 if ((obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFreeRatioKey
)))
1004 if ((num
= OSDynamicCast(OSNumber
, obj
)))
1005 gIOHibernateFreeRatio
= num
->unsigned32BitValue();
1008 if ((obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFreeTimeKey
)))
1010 if ((num
= OSDynamicCast(OSNumber
, obj
)))
1011 gIOHibernateFreeTime
= num
->unsigned32BitValue();
1014 if ((obj
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey
)))
1016 if ((str
= OSDynamicCast(OSString
, obj
)))
1017 strcpy(gIOHibernateFilename
, str
->getCStringNoCopy());
1021 if (!gIOHibernateMode
|| !gIOHibernateFilename
[0])
1022 return (kIOReturnUnsupported
);
1024 HIBLOG("hibernate image path: %s\n", gIOHibernateFilename
);
1028 vars
->srcBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,
1029 4 * page_size
, page_size
);
1030 vars
->ioBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,
1031 2 * kDefaultIOSize
, page_size
);
1033 if (!vars
->srcBuffer
|| !vars
->ioBuffer
)
1035 err
= kIOReturnNoMemory
;
1039 err
= IOPolledFileOpen(gIOHibernateFilename
, vars
->ioBuffer
,
1040 &vars
->fileVars
, &vars
->fileExtents
, &data
);
1041 if (KERN_SUCCESS
!= err
)
1043 HIBLOG("IOPolledFileOpen(%x)\n", err
);
1046 if (vars
->fileVars
->fileRef
)
1048 // invalidate the image file
1049 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderInvalidSignature
;
1050 int err
= kern_write_file(vars
->fileVars
->fileRef
, 0,
1051 (caddr_t
) gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
));
1052 if (KERN_SUCCESS
!= err
)
1053 HIBLOG("kern_write_file(%d)\n", err
);
1056 bzero(gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
));
1058 boolean_t encryptedswap
;
1059 err
= hibernate_setup(gIOHibernateCurrentHeader
,
1060 gIOHibernateFreeRatio
, gIOHibernateFreeTime
,
1061 &vars
->page_list
, &vars
->page_list_wired
, &encryptedswap
);
1062 if (KERN_SUCCESS
!= err
)
1064 HIBLOG("hibernate_setup(%d)\n", err
);
1069 gIOHibernateMode
^= kIOHibernateModeEncrypt
;
1071 vars
->videoAllocSize
= kVideoMapSize
;
1072 if (KERN_SUCCESS
!= kmem_alloc_pageable(kernel_map
, &vars
->videoMapping
, vars
->videoAllocSize
))
1073 vars
->videoMapping
= 0;
1075 // generate crypt keys
1076 for (uint32_t i
= 0; i
< sizeof(vars
->wiredCryptKey
); i
++)
1077 vars
->wiredCryptKey
[i
] = random();
1078 for (uint32_t i
= 0; i
< sizeof(vars
->cryptKey
); i
++)
1079 vars
->cryptKey
[i
] = random();
1083 IORegistryEntry
* regEntry
;
1084 if (!gIOOptionsEntry
)
1086 regEntry
= IORegistryEntry::fromPath("/options", gIODTPlane
);
1087 gIOOptionsEntry
= OSDynamicCast(IODTNVRAM
, regEntry
);
1088 if (regEntry
&& !gIOOptionsEntry
)
1089 regEntry
->release();
1091 if (!gIOChosenEntry
)
1092 gIOChosenEntry
= IORegistryEntry::fromPath("/chosen", gIODTPlane
);
1094 if (gIOOptionsEntry
)
1096 const OSSymbol
* sym
;
1098 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey
);
1101 gIOOptionsEntry
->setProperty(sym
, data
);
1108 char valueString
[16];
1110 vars
->saveBootDevice
= gIOOptionsEntry
->copyProperty(kIOSelectedBootDeviceKey
);
1113 OSData
* bootDevice
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOBootPathKey
));
1116 sym
= OSSymbol::withCStringNoCopy(kIOSelectedBootDeviceKey
);
1117 OSString
* str2
= OSString::withCStringNoCopy((const char *) bootDevice
->getBytesNoCopy());
1119 gIOOptionsEntry
->setProperty(sym
, str2
);
1125 data
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMemorySignatureKey
));
1128 vars
->haveFastBoot
= true;
1130 len
= sprintf(valueString
, "0x%lx", *((UInt32
*)data
->getBytesNoCopy()));
1131 data
= OSData::withBytes(valueString
, len
+ 1);
1132 sym
= OSSymbol::withCStringNoCopy(kIOHibernateMemorySignatureEnvKey
);
1134 gIOOptionsEntry
->setProperty(sym
, data
);
1140 data
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMachineSignatureKey
));
1142 gIOHibernateCurrentHeader
->machineSignature
= *((UInt32
*)data
->getBytesNoCopy());
1144 #endif /* __ppc__ */
1146 struct AppleRTCHibernateVars
1148 uint8_t signature
[4];
1150 uint8_t booterSignature
[20];
1151 uint8_t wiredCryptKey
[16];
1153 AppleRTCHibernateVars rtcVars
;
1155 rtcVars
.signature
[0] = 'A';
1156 rtcVars
.signature
[1] = 'A';
1157 rtcVars
.signature
[2] = 'P';
1158 rtcVars
.signature
[3] = 'L';
1159 rtcVars
.revision
= 1;
1160 bcopy(&vars
->wiredCryptKey
[0], &rtcVars
.wiredCryptKey
[0], sizeof(rtcVars
.wiredCryptKey
));
1161 if (gIOHibernateBootSignature
[0])
1165 for (uint32_t i
= 0;
1166 (c
= gIOHibernateBootSignature
[i
]) && (i
< (sizeof(rtcVars
.booterSignature
) << 1));
1177 value
= (value
<< 4) | c
;
1179 rtcVars
.booterSignature
[i
>> 1] = value
;
1182 data
= OSData::withBytes(&rtcVars
, sizeof(rtcVars
));
1185 IOService::getPMRootDomain()->setProperty(kIOHibernateRTCVariablesKey
, data
);
1190 data
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMachineSignatureKey
));
1192 gIOHibernateCurrentHeader
->machineSignature
= *((UInt32
*)data
->getBytesNoCopy());
1194 #else /* !__i386__ */
1195 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
1197 data
= OSData::withBytes(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
));
1198 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKeyKey
);
1200 gIOOptionsEntry
->setProperty(sym
, data
);
1205 if (gIOHibernateBootSignature
[0])
1207 data
= OSData::withCapacity(16);
1208 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey
);
1213 for (uint32_t i
= 0; (c
= gIOHibernateBootSignature
[i
]); i
++)
1223 value
= (value
<< 4) | c
;
1225 data
->appendBytes(&value
, sizeof(value
));
1227 gIOOptionsEntry
->setProperty(sym
, data
);
1235 if (!vars
->haveFastBoot
)
1237 // set boot volume to zero
1238 IODTPlatformExpert
* platform
= OSDynamicCast(IODTPlatformExpert
, IOService::getPlatform());
1239 if (platform
&& (kIOReturnSuccess
== platform
->readXPRAM(kXPRamAudioVolume
,
1240 &vars
->saveBootAudioVolume
, sizeof(vars
->saveBootAudioVolume
))))
1243 newVolume
= vars
->saveBootAudioVolume
& 0xf8;
1244 platform
->writeXPRAM(kXPRamAudioVolume
,
1245 &newVolume
, sizeof(newVolume
));
1248 #endif /* !__i386__ */
1252 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderSignature
;
1253 gIOHibernateState
= kIOHibernateStateHibernating
;
1260 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1263 IOHibernateSystemHasSlept(void)
1265 IOHibernateVars
* vars
= &gIOHibernateVars
;
1267 if ((vars
->previewData
= OSDynamicCast(OSData
,
1268 IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewBufferKey
))))
1270 vars
->previewBuffer
= IOMemoryDescriptor::withAddress(
1271 (void *) vars
->previewData
->getBytesNoCopy(),
1272 vars
->previewData
->getLength(),
1275 if (vars
->previewBuffer
&& (kIOReturnSuccess
!= vars
->previewBuffer
->prepare()))
1277 vars
->previewBuffer
->release();
1278 vars
->previewBuffer
= 0;
1280 if (!vars
->previewBuffer
)
1281 vars
->previewData
= 0;
1283 if (gIOOptionsEntry
)
1284 gIOOptionsEntry
->sync();
1286 return (kIOReturnSuccess
);
1289 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1292 IOHibernateSystemWake(void)
1294 IOHibernateVars
* vars
= &gIOHibernateVars
;
1296 hibernate_teardown(vars
->page_list
, vars
->page_list_wired
);
1298 if (vars
->videoMapping
)
1300 if (vars
->videoMapSize
)
1302 IOUnmapPages(kernel_map
, vars
->videoMapping
, vars
->videoMapSize
);
1303 if (vars
->videoAllocSize
)
1305 kmem_free(kernel_map
, trunc_page_32(vars
->videoMapping
), vars
->videoAllocSize
);
1308 if (vars
->previewBuffer
)
1310 vars
->previewBuffer
->release();
1311 vars
->previewBuffer
= 0;
1316 IOPolledFileClose(vars
->fileVars
);
1319 // invalidate nvram properties - (gIOOptionsEntry != 0) => nvram was touched
1322 OSData
* data
= OSData::withCapacity(4);
1323 if (gIOOptionsEntry
&& data
)
1325 const OSSymbol
* sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey
);
1328 gIOOptionsEntry
->setProperty(sym
, data
);
1331 sym
= OSSymbol::withCStringNoCopy(kIOSelectedBootDeviceKey
);
1334 if (vars
->saveBootDevice
)
1336 gIOOptionsEntry
->setProperty(sym
, vars
->saveBootDevice
);
1337 vars
->saveBootDevice
->release();
1341 sym
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKeyKey
);
1344 gIOOptionsEntry
->setProperty(sym
, data
);
1347 sym
= OSSymbol::withCStringNoCopy(kIOHibernateMemorySignatureEnvKey
);
1350 gIOOptionsEntry
->removeProperty(sym
);
1357 if (gIOOptionsEntry
)
1359 if (!vars
->haveFastBoot
)
1361 // reset boot audio volume
1362 IODTPlatformExpert
* platform
= OSDynamicCast(IODTPlatformExpert
, IOService::getPlatform());
1364 platform
->writeXPRAM(kXPRamAudioVolume
,
1365 &vars
->saveBootAudioVolume
, sizeof(vars
->saveBootAudioVolume
));
1368 // sync now to hardware if the booter has not
1369 if (kIOHibernateStateInactive
== gIOHibernateState
)
1370 gIOOptionsEntry
->sync();
1372 // just sync the variables in case a later panic syncs nvram (it won't sync variables)
1373 gIOOptionsEntry
->syncOFVariables();
1378 IOService::getPMRootDomain()->removeProperty(kIOHibernateRTCVariablesKey
);
1381 if (vars
->srcBuffer
)
1382 vars
->srcBuffer
->release();
1384 vars
->ioBuffer
->release();
1385 if (vars
->fileExtents
)
1386 vars
->fileExtents
->release();
1388 bzero(vars
, sizeof(*vars
));
1390 // gIOHibernateState = kIOHibernateStateInactive; // leave it for post wake code to see
1392 return (kIOReturnSuccess
);
1396 IOHibernateSystemPostWake(void)
1398 if (gIOHibernateFileRef
)
1400 // invalidate the image file
1401 gIOHibernateCurrentHeader
->signature
= kIOHibernateHeaderInvalidSignature
;
1402 int err
= kern_write_file(gIOHibernateFileRef
, 0,
1403 (caddr_t
) gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
));
1404 if (KERN_SUCCESS
!= err
)
1405 HIBLOG("kern_write_file(%d)\n", err
);
1407 kern_close_file_for_direct_io(gIOHibernateFileRef
);
1408 gIOHibernateFileRef
= 0;
1410 return (kIOReturnSuccess
);
1413 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1416 IOHibernateSystemInit(IOPMrootDomain
* rootDomain
)
1418 OSData
* data
= OSData::withBytesNoCopy(&gIOHibernateState
, sizeof(gIOHibernateState
));
1421 rootDomain
->setProperty(kIOHibernateStateKey
, data
);
1425 if (PE_parse_boot_arg("hfile", gIOHibernateFilename
))
1426 gIOHibernateMode
= kIOHibernateModeOn
;
1428 gIOHibernateFilename
[0] = 0;
1430 static SYSCTL_STRING(_kern
, OID_AUTO
, hibernatefile
,
1431 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
,
1432 gIOHibernateFilename
, sizeof(gIOHibernateFilename
), "");
1433 sysctl_register_oid(&sysctl__kern_hibernatefile
);
1435 static SYSCTL_STRING(_kern
, OID_AUTO
, bootsignature
,
1436 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
,
1437 gIOHibernateBootSignature
, sizeof(gIOHibernateBootSignature
), "");
1438 sysctl_register_oid(&sysctl__kern_bootsignature
);
1440 static SYSCTL_UINT(_kern
, OID_AUTO
, hibernatemode
,
1441 CTLFLAG_RW
| CTLFLAG_NOAUTO
| CTLFLAG_KERN
,
1442 &gIOHibernateMode
, 0, "");
1443 sysctl_register_oid(&sysctl__kern_hibernatemode
);
1446 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1449 hibernate_setup_for_wake(void)
1452 // go slow (state needed for wake)
1453 ml_set_processor_speed(1);
1457 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1459 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
1461 extern "C" boolean_t
1462 hibernate_write_image(void)
1464 IOHibernateImageHeader
* header
= gIOHibernateCurrentHeader
;
1465 IOHibernateVars
* vars
= &gIOHibernateVars
;
1466 IOPolledFileExtent
* fileExtents
;
1468 C_ASSERT(sizeof(IOHibernateImageHeader
) == 512);
1470 uint32_t pageCount
, pagesDone
;
1473 IOItemCount page
, count
;
1476 IOByteCount pageCompressedSize
;
1477 uint64_t compressedSize
, uncompressedSize
;
1478 uint64_t image1Size
= 0;
1479 uint32_t bitmap_size
;
1480 bool iterDone
, pollerOpen
, needEncryptStart
;
1481 uint32_t restore1Sum
, sum
, sum1
, sum2
;
1484 uint32_t pageAndCount
[2];
1486 AbsoluteTime startTime
, endTime
;
1487 AbsoluteTime allTime
, compTime
, decoTime
;
1489 uint32_t lastProgressStamp
= 0;
1490 uint32_t progressStamp
;
1492 hibernate_cryptvars_t _cryptvars
;
1493 hibernate_cryptvars_t
* cryptvars
= 0;
1495 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
|| !vars
->fileExtents
)
1496 return (false /* sleep */ );
1498 restore1Sum
= sum1
= sum2
= 0;
1500 // encryption data. "iv" is the "initial vector".
1501 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
1503 static const unsigned char first_iv
[AES_BLOCK_SIZE
]
1504 = { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c,
1505 0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda };
1507 cryptvars
= &gIOHibernateCryptWakeContext
;
1508 bzero(cryptvars
, sizeof(hibernate_cryptvars_t
));
1509 aes_encrypt_key(vars
->cryptKey
,
1510 kIOHibernateAESKeySize
,
1511 &cryptvars
->ctx
.encrypt
);
1512 aes_decrypt_key(vars
->cryptKey
,
1513 kIOHibernateAESKeySize
,
1514 &cryptvars
->ctx
.decrypt
);
1516 cryptvars
= &_cryptvars
;
1517 bzero(cryptvars
, sizeof(hibernate_cryptvars_t
));
1518 aes_encrypt_key(vars
->wiredCryptKey
,
1519 kIOHibernateAESKeySize
,
1520 &cryptvars
->ctx
.encrypt
);
1522 bcopy(&first_iv
[0], &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
);
1523 bzero(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
));
1524 bzero(&vars
->cryptKey
[0], sizeof(vars
->cryptKey
));
1525 bzero(gIOHibernateCryptWakeVars
, sizeof(hibernate_cryptwakevars_t
));
1528 hibernate_setup_for_wake();
1530 hibernate_page_list_setall(vars
->page_list
,
1531 vars
->page_list_wired
,
1534 HIBLOG("hibernate_page_list_setall found pageCount %d\n", pageCount
);
1536 fileExtents
= (IOPolledFileExtent
*) vars
->fileExtents
->getBytesNoCopy();
1539 count
= vars
->fileExtents
->getLength() / sizeof(IOPolledFileExtent
);
1540 for (page
= 0; page
< count
; page
++)
1542 HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page
,
1543 fileExtents
[page
].start
, fileExtents
[page
].length
,
1544 fileExtents
[page
].start
+ fileExtents
[page
].length
);
1548 needEncryptStart
= (0 != (kIOHibernateModeEncrypt
& gIOHibernateMode
));
1550 AbsoluteTime_to_scalar(&compTime
) = 0;
1551 AbsoluteTime_to_scalar(&decoTime
) = 0;
1553 clock_get_uptime(&allTime
);
1558 uncompressedSize
= 0;
1560 pageType
= 0; // wired pages first
1562 IOPolledFileSeek(vars
->fileVars
, sizeof(IOHibernateImageHeader
));
1564 HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n",
1565 ml_get_interrupts_enabled());
1566 err
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledBeforeSleepState
, vars
->ioBuffer
);
1567 HIBLOG("IOHibernatePollerOpen(%x)\n", err
);
1568 pollerOpen
= (kIOReturnSuccess
== err
);
1572 // copy file block extent list if larger than header
1574 count
= vars
->fileExtents
->getLength();
1575 if (count
> sizeof(header
->fileExtentMap
))
1577 count
-= sizeof(header
->fileExtentMap
);
1578 err
= IOPolledFileWrite(vars
->fileVars
,
1579 ((uint8_t *) &fileExtents
[0]) + sizeof(header
->fileExtentMap
), count
, cryptvars
);
1580 if (kIOReturnSuccess
!= err
)
1584 // copy out restore1 code
1586 page
= atop_32(sectHIBB
);
1587 count
= atop_32(round_page(sectHIBB
+ sectSizeHIB
)) - page
;
1588 header
->restore1CodePage
= page
;
1589 header
->restore1PageCount
= count
;
1590 header
->restore1CodeOffset
= ((uint32_t) &hibernate_machine_entrypoint
) - sectHIBB
;
1591 header
->restore1StackOffset
= ((uint32_t) &gIOHibernateRestoreStackEnd
[0]) - 64 - sectHIBB
;
1593 // sum __HIB sect, with zeros for the stack
1594 src
= (uint8_t *) trunc_page(sectHIBB
);
1595 for (page
= 0; page
< count
; page
++)
1597 if ((src
< &gIOHibernateRestoreStack
[0]) || (src
>= &gIOHibernateRestoreStackEnd
[0]))
1598 restore1Sum
+= hibernate_sum(src
, page_size
);
1600 restore1Sum
+= 0x10000001;
1605 // write the __HIB sect, with zeros for the stack
1607 src
= (uint8_t *) trunc_page(sectHIBB
);
1608 count
= ((uint32_t) &gIOHibernateRestoreStack
[0]) - trunc_page(sectHIBB
);
1611 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
1612 if (kIOReturnSuccess
!= err
)
1615 err
= IOPolledFileWrite(vars
->fileVars
,
1617 &gIOHibernateRestoreStackEnd
[0] - &gIOHibernateRestoreStack
[0],
1619 if (kIOReturnSuccess
!= err
)
1621 src
= &gIOHibernateRestoreStackEnd
[0];
1622 count
= round_page(sectHIBB
+ sectSizeHIB
) - ((uint32_t) src
);
1625 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
1626 if (kIOReturnSuccess
!= err
)
1630 // write the preview buffer
1635 if (vars
->previewData
)
1641 phys64
= vars
->previewBuffer
->getPhysicalSegment64(count
, &segLen
);
1642 pageAndCount
[0] = atop_64(phys64
);
1643 pageAndCount
[1] = atop_32(segLen
);
1644 err
= IOPolledFileWrite(vars
->fileVars
,
1645 (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),
1647 if (kIOReturnSuccess
!= err
)
1650 ppnum
+= sizeof(pageAndCount
);
1653 if (kIOReturnSuccess
!= err
)
1656 src
= (uint8_t *) vars
->previewData
->getBytesNoCopy();
1657 count
= vars
->previewData
->getLength();
1659 header
->previewPageListSize
= ppnum
;
1660 header
->previewSize
= count
+ ppnum
;
1662 for (page
= 0; page
< count
; page
+= page_size
)
1663 sum1
+= hibernate_sum(src
+ page
, page_size
);
1665 err
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
);
1666 if (kIOReturnSuccess
!= err
)
1670 // mark areas for no save
1673 (phys64
= vars
->ioBuffer
->getPhysicalSegment64(count
, &segLen
));
1676 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
1677 atop_64(phys64
), atop_32(segLen
),
1678 kIOHibernatePageStateFree
);
1679 pageCount
-= atop_32(segLen
);
1683 (phys64
= vars
->srcBuffer
->getPhysicalSegment64(count
, &segLen
));
1686 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
1687 atop_64(phys64
), atop_32(segLen
),
1688 kIOHibernatePageStateFree
);
1689 pageCount
-= atop_32(segLen
);
1692 // copy out bitmap of pages available for trashing during restore
1694 bitmap_size
= vars
->page_list_wired
->list_size
;
1695 src
= (uint8_t *) vars
->page_list_wired
;
1696 err
= IOPolledFileWrite(vars
->fileVars
, src
, bitmap_size
, cryptvars
);
1697 if (kIOReturnSuccess
!= err
)
1700 // mark more areas for no save, but these are not available
1701 // for trashing during restore
1703 hibernate_page_list_set_volatile(vars
->page_list
, vars
->page_list_wired
, &pageCount
);
1705 page
= atop_32(sectHIBB
);
1706 count
= atop_32(round_page(sectHIBB
+ sectSizeHIB
)) - page
;
1707 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
1709 kIOHibernatePageStateFree
);
1712 if (vars
->previewBuffer
) for (count
= 0;
1713 (phys64
= vars
->previewBuffer
->getPhysicalSegment64(count
, &segLen
));
1716 hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,
1717 atop_64(phys64
), atop_32(segLen
),
1718 kIOHibernatePageStateFree
);
1719 pageCount
-= atop_32(segLen
);
1722 src
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy();
1727 HIBLOG("writing %d pages\n", pageCount
);
1731 count
= hibernate_page_list_iterate(pageType
? vars
->page_list
: vars
->page_list_wired
,
1733 // kprintf("[%d](%x : %x)\n", pageType, ppnum, count);
1737 pageAndCount
[0] = ppnum
;
1738 pageAndCount
[1] = count
;
1739 err
= IOPolledFileWrite(vars
->fileVars
,
1740 (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),
1742 if (kIOReturnSuccess
!= err
)
1745 for (page
= 0; page
< count
; page
++)
1747 err
= IOMemoryDescriptorWriteFromPhysical(vars
->srcBuffer
, 0, ptoa_64(ppnum
), page_size
);
1750 HIBLOG("IOMemoryDescriptorWriteFromPhysical %d [%d] %x\n", __LINE__
, ppnum
, err
);
1754 sum
= hibernate_sum(src
, page_size
);
1756 clock_get_uptime(&startTime
);
1758 pageCompressedSize
= WKdm_compress ((WK_word
*) src
, (WK_word
*) (src
+ page_size
), PAGE_SIZE_IN_WORDS
);
1760 clock_get_uptime(&endTime
);
1761 ADD_ABSOLUTETIME(&compTime
, &endTime
);
1762 SUB_ABSOLUTETIME(&compTime
, &startTime
);
1764 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
1765 pageCompressedSize
= (pageCompressedSize
+ AES_BLOCK_SIZE
- 1) & ~(AES_BLOCK_SIZE
- 1);
1767 if (pageCompressedSize
> page_size
)
1769 // HIBLOG("------------lose: %d\n", pageCompressedSize);
1770 pageCompressedSize
= page_size
;
1773 if (pageCompressedSize
!= page_size
)
1774 data
= (src
+ page_size
);
1778 tag
= pageCompressedSize
| kIOHibernateTagSignature
;
1785 if (needEncryptStart
&& (ppnum
>= atop_32(sectDATAB
)))
1787 // start encrypting partway into the data about to be written
1788 vars
->fileVars
->encryptStart
= (vars
->fileVars
->position
+ AES_BLOCK_SIZE
- 1)
1789 & ~(AES_BLOCK_SIZE
- 1);
1790 needEncryptStart
= false;
1793 err
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *) &tag
, sizeof(tag
), cryptvars
);
1794 if (kIOReturnSuccess
!= err
)
1797 err
= IOPolledFileWrite(vars
->fileVars
, data
, (pageCompressedSize
+ 3) & ~3, cryptvars
);
1798 if (kIOReturnSuccess
!= err
)
1801 compressedSize
+= pageCompressedSize
;
1802 if (pageCompressedSize
)
1803 uncompressedSize
+= page_size
;
1807 if (0 == (8191 & pagesDone
))
1809 clock_get_uptime(&endTime
);
1810 SUB_ABSOLUTETIME(&endTime
, &allTime
);
1811 absolutetime_to_nanoseconds(endTime
, &nsec
);
1812 progressStamp
= nsec
/ 750000000ULL;
1813 if (progressStamp
!= lastProgressStamp
)
1815 lastProgressStamp
= progressStamp
;
1816 HIBPRINT("pages %d (%d%%)\n", pagesDone
, (100 * pagesDone
) / pageCount
);
1820 if (kIOReturnSuccess
!= err
)
1822 if (iterDone
&& !pageType
)
1824 err
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
);
1825 if (kIOReturnSuccess
!= err
)
1831 image1Size
= vars
->fileVars
->position
;
1834 bcopy(&cryptvars
->aes_iv
[0],
1835 &gIOHibernateCryptWakeContext
.aes_iv
[0],
1836 sizeof(cryptvars
->aes_iv
));
1837 cryptvars
= &gIOHibernateCryptWakeContext
;
1839 HIBLOG("image1Size %qd\n", image1Size
);
1843 if (kIOReturnSuccess
!= err
)
1845 err
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
);
1846 if (kIOReturnSuccess
!= err
)
1851 header
->imageSize
= vars
->fileVars
->position
;
1852 header
->image1Size
= image1Size
;
1853 header
->bitmapSize
= bitmap_size
;
1854 header
->pageCount
= pageCount
;
1855 header
->encryptStart
= vars
->fileVars
->encryptStart
;
1857 header
->restore1Sum
= restore1Sum
;
1858 header
->image1Sum
= sum1
;
1859 header
->image2Sum
= sum2
;
1861 count
= vars
->fileExtents
->getLength();
1862 if (count
> sizeof(header
->fileExtentMap
))
1864 header
->fileExtentMapSize
= count
;
1865 count
= sizeof(header
->fileExtentMap
);
1868 header
->fileExtentMapSize
= sizeof(header
->fileExtentMap
);
1869 bcopy(&fileExtents
[0], &header
->fileExtentMap
[0], count
);
1871 IOPolledFileSeek(vars
->fileVars
, 0);
1872 err
= IOPolledFileWrite(vars
->fileVars
,
1873 (uint8_t *) header
, sizeof(IOHibernateImageHeader
),
1875 if (kIOReturnSuccess
!= err
)
1877 err
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
);
1878 if (kIOReturnSuccess
!= err
)
1880 err
= IOHibernatePollerIODone(vars
->fileVars
);
1881 if (kIOReturnSuccess
!= err
)
1886 clock_get_uptime(&endTime
);
1887 SUB_ABSOLUTETIME(&endTime
, &allTime
);
1888 absolutetime_to_nanoseconds(endTime
, &nsec
);
1889 HIBLOG("all time: %qd ms, ",
1892 absolutetime_to_nanoseconds(compTime
, &nsec
);
1893 HIBLOG("comp time: %qd ms, ",
1896 absolutetime_to_nanoseconds(decoTime
, &nsec
);
1897 HIBLOG("deco time: %qd ms, ",
1900 HIBLOG("\nimage %qd, uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n",
1902 uncompressedSize
, atop_32(uncompressedSize
), compressedSize
,
1903 (int) ((compressedSize
* 100ULL) / uncompressedSize
),
1907 IOHibernatePollerClose(vars
->fileVars
, kIOPolledBeforeSleepState
);
1909 HIBLOG("hibernate_write_image done(%x)\n", err
);
1911 // should we come back via regular wake, set the state in memory.
1912 gIOHibernateState
= kIOHibernateStateInactive
;
1914 if ((kIOReturnSuccess
== err
) && !(kIOHibernateModeSleep
& gIOHibernateMode
))
1915 return (true /* power down */ );
1917 return (false /* sleep */ );
1920 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1922 DECLARE_IOHIBERNATEPROGRESSALPHA
1925 ProgressUpdate(hibernate_graphics_t
* display
, uint8_t * screen
, int32_t firstBlob
, int32_t select
)
1927 uint32_t rowBytes
, pixelShift
;
1929 int32_t blob
, lastBlob
;
1930 uint32_t alpha
, in
, color
, result
;
1932 uint32_t saveindex
[kIOHibernateProgressCount
] = { 0 };
1934 pixelShift
= display
->depth
>> 4;
1938 rowBytes
= display
->rowBytes
;
1940 screen
+= ((display
->width
1941 - kIOHibernateProgressCount
* (kIOHibernateProgressWidth
+ kIOHibernateProgressSpacing
)) << (pixelShift
- 1))
1942 + (display
->height
- kIOHibernateProgressOriginY
- kIOHibernateProgressHeight
) * rowBytes
;
1944 lastBlob
= (select
< kIOHibernateProgressCount
) ? select
: (kIOHibernateProgressCount
- 1);
1946 screen
+= (firstBlob
* (kIOHibernateProgressWidth
+ kIOHibernateProgressSpacing
)) << pixelShift
;
1948 for (y
= 0; y
< kIOHibernateProgressHeight
; y
++)
1950 out
= screen
+ y
* rowBytes
;
1951 for (blob
= firstBlob
; blob
<= lastBlob
; blob
++)
1953 color
= (blob
< select
) ? kIOHibernateProgressLightGray
: kIOHibernateProgressMidGray
;
1954 for (x
= 0; x
< kIOHibernateProgressWidth
; x
++)
1956 alpha
= gIOHibernateProgressAlpha
[y
][x
];
1962 in
= display
->progressSaveUnder
[blob
][saveindex
[blob
]++];
1963 result
= ((255 - alpha
) * in
+ alpha
* result
+ 0xff) / 255;
1965 if (1 == pixelShift
)
1968 *((uint16_t *)out
) = (result
<< 10) | (result
<< 5) | result
; // 16
1971 *((uint32_t *)out
) = (result
<< 16) | (result
<< 8) | result
; // 32
1973 out
+= (1 << pixelShift
);
1975 out
+= (kIOHibernateProgressSpacing
<< pixelShift
);
1980 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1983 hibernate_machine_init(void)
1988 AbsoluteTime allTime
, endTime
;
1990 uint32_t lastProgressStamp
= 0;
1991 uint32_t progressStamp
;
1992 uint64_t progressZeroPosition
= 0;
1993 uint32_t blob
, lastBlob
= (uint32_t) -1L;
1994 hibernate_cryptvars_t
* cryptvars
= 0;
1996 IOHibernateVars
* vars
= &gIOHibernateVars
;
1998 if (!vars
->fileVars
|| !vars
->fileVars
->pollers
|| !vars
->fileExtents
)
2001 sum
= gIOHibernateCurrentHeader
->actualImage1Sum
;
2002 pagesDone
= gIOHibernateCurrentHeader
->actualUncompressedPages
;
2004 HIBLOG("hibernate_machine_init: state %d, image pages %d, sum was %x, image1Size %qx, conflictCount %d, nextFree %x\n",
2005 gIOHibernateState
, pagesDone
, sum
, gIOHibernateCurrentHeader
->image1Size
,
2006 gIOHibernateCurrentHeader
->conflictCount
, gIOHibernateCurrentHeader
->nextFree
);
2008 if (kIOHibernateStateWakingFromHibernate
!= gIOHibernateState
)
2010 HIBLOG("regular wake\n");
2014 HIBPRINT("diag %x %x %x %x\n",
2015 gIOHibernateCurrentHeader
->diag
[0], gIOHibernateCurrentHeader
->diag
[1],
2016 gIOHibernateCurrentHeader
->diag
[2], gIOHibernateCurrentHeader
->diag
[3]);
2018 HIBPRINT("video %x %d %d %d\n",
2019 gIOHibernateGraphicsInfo
->physicalAddress
, gIOHibernateGraphicsInfo
->depth
,
2020 gIOHibernateGraphicsInfo
->width
, gIOHibernateGraphicsInfo
->height
);
2022 if ((kIOHibernateModeDiscardCleanActive
| kIOHibernateModeDiscardCleanInactive
) & gIOHibernateMode
)
2023 hibernate_page_list_discard(vars
->page_list
);
2025 boot_args
*args
= (boot_args
*) PE_state
.bootArgs
;
2027 if (vars
->videoMapping
2028 && gIOHibernateGraphicsInfo
->physicalAddress
2029 && (args
->Video
.v_baseAddr
== gIOHibernateGraphicsInfo
->physicalAddress
))
2031 vars
->videoMapSize
= round_page(gIOHibernateGraphicsInfo
->height
2032 * gIOHibernateGraphicsInfo
->rowBytes
);
2033 IOMapPages(kernel_map
,
2034 vars
->videoMapping
, gIOHibernateGraphicsInfo
->physicalAddress
,
2035 vars
->videoMapSize
, kIOMapInhibitCache
);
2038 uint8_t * src
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy();
2040 if (gIOHibernateWakeMapSize
)
2042 err
= IOMemoryDescriptorWriteFromPhysical(vars
->srcBuffer
, 0, ptoa_64(gIOHibernateWakeMap
),
2043 gIOHibernateWakeMapSize
);
2044 if (kIOReturnSuccess
== err
)
2045 hibernate_newruntime_map(src
, gIOHibernateWakeMapSize
,
2046 gIOHibernateCurrentHeader
->systemTableOffset
);
2047 gIOHibernateWakeMap
= 0;
2048 gIOHibernateWakeMapSize
= 0;
2051 uint32_t decoOffset
;
2053 clock_get_uptime(&allTime
);
2055 HIBLOG("IOHibernatePollerOpen(), ml_get_interrupts_enabled %d\n", ml_get_interrupts_enabled());
2056 err
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledAfterSleepState
, 0);
2057 HIBLOG("IOHibernatePollerOpen(%x)\n", err
);
2059 if (gIOHibernateCurrentHeader
->previewSize
)
2060 progressZeroPosition
= gIOHibernateCurrentHeader
->previewSize
2061 + gIOHibernateCurrentHeader
->fileExtentMapSize
2062 - sizeof(gIOHibernateCurrentHeader
->fileExtentMap
)
2063 + ptoa_64(gIOHibernateCurrentHeader
->restore1PageCount
);
2065 IOPolledFileSeek(vars
->fileVars
, gIOHibernateCurrentHeader
->image1Size
);
2067 if (vars
->videoMapping
)
2069 lastBlob
= ((vars
->fileVars
->position
- progressZeroPosition
) * kIOHibernateProgressCount
)
2070 / (gIOHibernateCurrentHeader
->imageSize
- progressZeroPosition
);
2071 ProgressUpdate(gIOHibernateGraphicsInfo
, (uint8_t *) vars
->videoMapping
, 0, lastBlob
);
2074 cryptvars
= (kIOHibernateModeEncrypt
& gIOHibernateMode
) ? &gIOHibernateCryptWakeContext
: 0;
2075 if (kIOHibernateModeEncrypt
& gIOHibernateMode
)
2077 cryptvars
= &gIOHibernateCryptWakeContext
;
2078 bcopy(&gIOHibernateCryptWakeVars
->aes_iv
[0],
2079 &cryptvars
->aes_iv
[0],
2080 sizeof(cryptvars
->aes_iv
));
2083 // kick off the read ahead
2084 vars
->fileVars
->io
= false;
2085 vars
->fileVars
->bufferHalf
= 0;
2086 vars
->fileVars
->bufferLimit
= 0;
2087 vars
->fileVars
->lastRead
= 0;
2088 vars
->fileVars
->bufferOffset
= vars
->fileVars
->bufferLimit
;
2090 IOPolledFileRead(vars
->fileVars
, 0, 0, cryptvars
);
2091 vars
->fileVars
->bufferOffset
= vars
->fileVars
->bufferLimit
;
2094 HIBLOG("hibernate_machine_init reading\n");
2096 uint32_t * header
= (uint32_t *) src
;
2104 vm_offset_t ppnum
, compressedSize
;
2106 IOPolledFileRead(vars
->fileVars
, src
, 8, cryptvars
);
2111 // HIBPRINT("(%x, %x)\n", ppnum, count);
2116 for (page
= 0; page
< count
; page
++)
2118 IOPolledFileRead(vars
->fileVars
, (uint8_t *) &tag
, 4, cryptvars
);
2120 compressedSize
= kIOHibernateTagLength
& tag
;
2121 if (!compressedSize
)
2128 IOPolledFileRead(vars
->fileVars
, src
, (compressedSize
+ 3) & ~3, cryptvars
);
2130 if (compressedSize
!= page_size
)
2132 decoOffset
= page_size
;
2133 WKdm_decompress((WK_word
*) src
, (WK_word
*) (src
+ decoOffset
), PAGE_SIZE_IN_WORDS
);
2138 sum
+= hibernate_sum((src
+ decoOffset
), page_size
);
2140 err
= IOMemoryDescriptorReadToPhysical(vars
->srcBuffer
, decoOffset
, ptoa_64(ppnum
), page_size
);
2142 HIBLOG("IOMemoryDescriptorReadToPhysical [%d] %x\n", ppnum
, err
);
2147 if (vars
->videoMapping
&& (0 == (255 & pagesDone
)))
2149 blob
= ((vars
->fileVars
->position
- progressZeroPosition
) * kIOHibernateProgressCount
)
2150 / (gIOHibernateCurrentHeader
->imageSize
- progressZeroPosition
);
2151 if (blob
!= lastBlob
)
2153 ProgressUpdate(gIOHibernateGraphicsInfo
, (uint8_t *) vars
->videoMapping
, lastBlob
, blob
);
2158 if (0 == (8191 & pagesDone
))
2160 clock_get_uptime(&endTime
);
2161 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2162 absolutetime_to_nanoseconds(endTime
, &nsec
);
2163 progressStamp
= nsec
/ 750000000ULL;
2164 if (progressStamp
!= lastProgressStamp
)
2166 lastProgressStamp
= progressStamp
;
2167 HIBPRINT("pages %d (%d%%)\n", pagesDone
,
2168 (100 * pagesDone
) / gIOHibernateCurrentHeader
->pageCount
);
2175 gIOHibernateCurrentHeader
->actualImage2Sum
= sum
;
2177 if (vars
->fileVars
->io
)
2178 (void) IOHibernatePollerIODone(vars
->fileVars
);
2180 err
= IOHibernatePollerClose(vars
->fileVars
, kIOPolledAfterSleepState
);
2182 if (vars
->videoMapping
)
2183 ProgressUpdate(gIOHibernateGraphicsInfo
,
2184 (uint8_t *) vars
->videoMapping
, 0, kIOHibernateProgressCount
);
2186 clock_get_uptime(&endTime
);
2187 SUB_ABSOLUTETIME(&endTime
, &allTime
);
2188 absolutetime_to_nanoseconds(endTime
, &nsec
);
2190 HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %qd ms\n",
2191 pagesDone
, sum
, nsec
/ 1000000ULL);
2194 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */