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 segment "__HIB" is written uncompressed to the image. This segment 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   segment "__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 <libkern/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 <vm/WKdm_new.h> 
 169 #include "IOKitKernelInternal.h" 
 170 #include <pexpert/device_tree.h> 
 172 #include <machine/pal_routines.h> 
 173 #include <machine/pal_hibernate.h> 
 174 #include <i386/tsc.h> 
 176 extern "C" addr64_t             
kvtophys(vm_offset_t va
); 
 177 extern "C" ppnum_t              
pmap_find_phys(pmap_t pmap
, addr64_t va
); 
 179 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 181 #define DISABLE_TRIM            0 
 182 #define TRIM_DELAY              5000 
 184 extern unsigned int             save_kdebug_enable
; 
 185 extern uint32_t                 gIOHibernateState
; 
 186 uint32_t                        gIOHibernateMode
; 
 187 static char                     gIOHibernateBootSignature
[256+1]; 
 188 static char                     gIOHibernateFilename
[MAXPATHLEN
+1]; 
 189 static uint32_t                 gIOHibernateFreeRatio 
= 0;       // free page target (percent) 
 190 uint32_t                        gIOHibernateFreeTime  
= 0*1000;  // max time to spend freeing pages (ms) 
 191 static uint64_t                 gIOHibernateCompression 
= 0x80;  // default compression 50% 
 193 static IODTNVRAM 
*              gIOOptionsEntry
; 
 194 static IORegistryEntry 
*        gIOChosenEntry
; 
 195 #if defined(__i386__) || defined(__x86_64__) 
 196 static const OSSymbol 
*         gIOCreateEFIDevicePathSymbol
; 
 197 static const OSSymbol 
*         gIOHibernateRTCVariablesKey
; 
 198 static const OSSymbol 
*         gIOHibernateBoot0082Key
; 
 199 static const OSSymbol 
*         gIOHibernateBootNextKey
; 
 200 static OSData 
*                 gIOHibernateBoot0082Data
; 
 201 static OSData 
*                 gIOHibernateBootNextData
; 
 202 static OSObject 
*               gIOHibernateBootNextSave
; 
 205 static IOLock 
*                           gFSLock
; 
 206 static uint32_t                           gFSState
; 
 207 static IOPolledFileIOVars                 gFileVars
; 
 208 static IOHibernateVars                    gIOHibernateVars
; 
 209 static struct kern_direct_file_io_ref_t 
* gIOHibernateFileRef
; 
 210 static hibernate_cryptvars_t              gIOHibernateCryptWakeContext
; 
 211 static hibernate_graphics_t               _hibernateGraphics
; 
 212 static hibernate_graphics_t 
*             gIOHibernateGraphicsInfo 
= &_hibernateGraphics
; 
 213 static hibernate_statistics_t             _hibernateStats
; 
 214 static hibernate_statistics_t 
*           gIOHibernateStats 
= &_hibernateStats
; 
 224 static IOReturn 
IOHibernateDone(IOHibernateVars 
* vars
); 
 226 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 228 enum { kXPRamAudioVolume 
= 8 }; 
 229 enum { kDefaultIOSize 
= 128 * 1024 }; 
 230 enum { kVideoMapSize  
= 32 * 1024 * 1024 }; 
 232 #ifndef kIOMediaPreferredBlockSizeKey 
 233 #define kIOMediaPreferredBlockSizeKey   "Preferred Block Size" 
 236 #ifndef kIOBootPathKey   
 237 #define kIOBootPathKey                  "bootpath" 
 239 #ifndef kIOSelectedBootDeviceKey         
 240 #define kIOSelectedBootDeviceKey        "boot-device" 
 244 enum { kIOHibernateMinPollersNeeded 
= 2 }; 
 246 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 248 // copy from phys addr to MD 
 251 IOMemoryDescriptorWriteFromPhysical(IOMemoryDescriptor 
* md
, 
 252                                     IOByteCount offset
, addr64_t bytes
, IOByteCount length
) 
 254     addr64_t srcAddr 
= bytes
; 
 255     IOByteCount remaining
; 
 257     remaining 
= length 
= min(length
, md
->getLength() - offset
); 
 258     while (remaining
) { // (process another target segment?) 
 262         dstAddr64 
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
); 
 266         // Clip segment length to remaining 
 267         if (dstLen 
> remaining
) 
 271         bcopy_phys(srcAddr
, dstAddr64
, dstLen
); 
 273         copypv(srcAddr
, dstAddr64
, dstLen
, 
 274                             cppvPsnk 
| cppvFsnk 
| cppvNoRefSrc 
| cppvNoModSnk 
| cppvKmap
); 
 283     return remaining 
? kIOReturnUnderrun 
: kIOReturnSuccess
; 
 286 // copy from MD to phys addr 
 289 IOMemoryDescriptorReadToPhysical(IOMemoryDescriptor 
* md
, 
 290                                  IOByteCount offset
, addr64_t bytes
, IOByteCount length
) 
 292     addr64_t dstAddr 
= bytes
; 
 293     IOByteCount remaining
; 
 295     remaining 
= length 
= min(length
, md
->getLength() - offset
); 
 296     while (remaining
) { // (process another target segment?) 
 300         srcAddr64 
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
); 
 304         // Clip segment length to remaining 
 305         if (dstLen 
> remaining
) 
 309         bcopy_phys(srcAddr64
, dstAddr
, dstLen
); 
 311         copypv(srcAddr
, dstAddr64
, dstLen
, 
 312                             cppvPsnk 
| cppvFsnk 
| cppvNoRefSrc 
| cppvNoModSnk 
| cppvKmap
); 
 321     return remaining 
? kIOReturnUnderrun 
: kIOReturnSuccess
; 
 324 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 327 hibernate_set_page_state(hibernate_page_list_t 
* page_list
, hibernate_page_list_t 
* page_list_wired
, 
 328                                 vm_offset_t ppnum
, vm_offset_t count
, uint32_t kind
) 
 333       case kIOHibernatePageStateUnwiredSave
: 
 335         for (; ppnum 
< count
; ppnum
++) 
 337             hibernate_page_bitset(page_list
,       FALSE
, ppnum
); 
 338             hibernate_page_bitset(page_list_wired
, TRUE
,  ppnum
); 
 341       case kIOHibernatePageStateWiredSave
: 
 343         for (; ppnum 
< count
; ppnum
++) 
 345             hibernate_page_bitset(page_list
,       FALSE
, ppnum
); 
 346             hibernate_page_bitset(page_list_wired
, FALSE
, ppnum
); 
 349       case kIOHibernatePageStateFree
: 
 351         for (; ppnum 
< count
; ppnum
++) 
 353             hibernate_page_bitset(page_list
,       TRUE
, ppnum
); 
 354             hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
); 
 358         panic("hibernate_set_page_state"); 
 363 hibernate_page_list_iterate(hibernate_page_list_t 
* list
, vm_offset_t 
* pPage
) 
 365     uint32_t             page 
= *pPage
; 
 367     hibernate_bitmap_t 
* bitmap
; 
 369     while ((bitmap 
= hibernate_page_bitmap_pin(list
, &page
))) 
 371         count 
= hibernate_page_bitmap_count(bitmap
, TRUE
, page
); 
 375         if (page 
<= bitmap
->last_page
) 
 381         count 
= hibernate_page_bitmap_count(bitmap
, FALSE
, page
); 
 388 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 391 IOHibernatePollerProbe(IOPolledFileIOVars 
* vars
, IOService 
* target
) 
 393     IOReturn            err 
= kIOReturnError
; 
 395     IOPolledInterface 
* poller
; 
 397     for (idx 
= vars
->pollers
->getCount() - 1; idx 
>= 0; idx
--) 
 399         poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
); 
 400         err 
= poller
->probe(target
); 
 403             HIBLOG("IOPolledInterface::probe[%d] 0x%x\n", idx
, err
); 
 412 IOHibernatePollerOpen(IOPolledFileIOVars 
* vars
, uint32_t state
, IOMemoryDescriptor 
* md
) 
 414     IOReturn            err 
= kIOReturnError
; 
 416     IOPolledInterface 
* poller
; 
 418     for (idx 
= vars
->pollers
->getCount() - 1; idx 
>= 0; idx
--) 
 420         poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
); 
 421         err 
= poller
->open(state
, md
); 
 424             HIBLOG("IOPolledInterface::open[%d] 0x%x\n", idx
, err
); 
 433 IOHibernatePollerClose(IOPolledFileIOVars 
* vars
, uint32_t state
) 
 435     IOReturn            err 
= kIOReturnError
; 
 437     IOPolledInterface 
* poller
; 
 440          (poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
)); 
 443         err 
= poller
->close(state
); 
 445             HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx
, err
); 
 452 IOHibernatePollerIOComplete(void *   target
, 
 455                             UInt64   actualByteCount
) 
 457     IOPolledFileIOVars 
* vars 
= (IOPolledFileIOVars 
*) parameter
; 
 459     vars
->ioStatus 
= status
; 
 463 IOHibernatePollerIO(IOPolledFileIOVars 
* vars
,  
 464                     uint32_t operation
, uint32_t bufferOffset
,  
 465                     uint64_t deviceOffset
, uint64_t length
) 
 468     IOReturn            err 
= kIOReturnError
; 
 469     IOPolledInterface 
* poller
; 
 470     IOPolledCompletion  completion
; 
 472     completion
.target    
= 0; 
 473     completion
.action    
= &IOHibernatePollerIOComplete
; 
 474     completion
.parameter 
= vars
; 
 478     poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(0); 
 479     err 
= poller
->startIO(operation
, bufferOffset
, deviceOffset 
+ vars
->block0
, length
, completion
); 
 481         HIBLOG("IOPolledInterface::startIO[%d] 0x%x\n", 0, err
); 
 487 IOHibernatePollerIODone(IOPolledFileIOVars 
* vars
, bool abortable
) 
 489     IOReturn            err 
= kIOReturnSuccess
; 
 491     IOPolledInterface 
* poller
; 
 493     while (-1 == vars
->ioStatus
) 
 496             (poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
)); 
 500             newErr 
= poller
->checkForWork(); 
 501             if ((newErr 
== kIOReturnAborted
) && !abortable
) 
 502                 newErr 
= kIOReturnSuccess
; 
 503             if (kIOReturnSuccess 
== err
) 
 508     if ((kIOReturnSuccess 
== err
) && abortable 
&& hibernate_should_abort()) 
 510         err 
= kIOReturnAborted
; 
 511         HIBLOG("IOPolledInterface::checkForWork sw abort\n"); 
 516         HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx
, err
); 
 520         err 
= vars
->ioStatus
; 
 521         if (kIOReturnSuccess 
!= err
) 
 522             HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err
); 
 529 IOPolledInterface::checkAllForWork(void) 
 531     IOReturn            err 
= kIOReturnNotReady
; 
 533     IOPolledInterface 
* poller
; 
 535     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
 537     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers
) 
 541             (poller 
= (IOPolledInterface 
*) vars
->fileVars
->pollers
->getObject(idx
)); 
 544         err 
= poller
->checkForWork(); 
 546             HIBLOG("IOPolledInterface::checkAllForWork[%d] 0x%x\n", idx
, err
); 
 552 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 554 struct _OpenFileContext
 
 561 file_extent_callback(void * ref
, uint64_t start
, uint64_t length
) 
 563     _OpenFileContext 
* ctx 
= (_OpenFileContext 
*) ref
; 
 564     IOPolledFileExtent extent
; 
 566     extent
.start  
= start
; 
 567     extent
.length 
= length
; 
 569     HIBLOG("[0x%qx, 0x%qx]\n", start
, length
); 
 571     ctx
->extents
->appendBytes(&extent
, sizeof(extent
)); 
 576 IOCopyMediaForDev(dev_t device
) 
 578     OSDictionary 
* matching
; 
 581     IOService 
*    result 
= 0; 
 583     matching 
= IOService::serviceMatching("IOMedia"); 
 588         num 
= OSNumber::withNumber(major(device
), 32); 
 591         matching
->setObject(kIOBSDMajorKey
, num
); 
 593         num 
= OSNumber::withNumber(minor(device
), 32); 
 596         matching
->setObject(kIOBSDMinorKey
, num
); 
 600         iter 
= IOService::getMatchingServices(matching
); 
 603             result 
= (IOService 
*) iter
->getNextObject(); 
 615 IOPolledFileOpen( const char * filename
, uint64_t setFileSize
, 
 616                   IOBufferMemoryDescriptor 
* ioBuffer
,  
 617                   IOPolledFileIOVars 
** fileVars
, OSData 
** fileExtents
, 
 618                   OSData 
** imagePath
, uint8_t * volumeCryptKey
) 
 620     IOReturn                    err 
= kIOReturnSuccess
; 
 621     IOPolledFileIOVars 
*        vars
; 
 622     _OpenFileContext            ctx
; 
 623     OSData 
*                    extentsData
; 
 625     IOService 
*                 part 
= 0; 
 626     OSString 
*                  keyUUID 
= 0; 
 627     OSString 
*                  keyStoreUUID 
= 0; 
 629     dev_t                       hibernate_image_dev
; 
 631     AbsoluteTime                startTime
, endTime
; 
 634     vars 
= IONew(IOPolledFileIOVars
, 1); 
 635     if (!vars
) return (kIOReturnNoMemory
); 
 636     bzero(vars
, sizeof(*vars
)); 
 641         vars
->buffer       
= (uint8_t *) ioBuffer
->getBytesNoCopy(); 
 642         vars
->bufferHalf   
= 0; 
 643         vars
->bufferOffset 
= 0; 
 644         vars
->bufferSize   
= ioBuffer
->getLength() >> 1; 
 646         extentsData 
= OSData::withCapacity(32); 
 647         ctx
.extents 
= extentsData
; 
 649         clock_get_uptime(&startTime
); 
 650         vars
->fileRef 
= kern_open_file_for_direct_io(filename
,  
 651                                                     &file_extent_callback
, &ctx
,  
 654                                                     0, (caddr_t
) gIOHibernateCurrentHeader
,  
 655                                                     sizeof(IOHibernateImageHeader
), 
 658                                                     &hibernate_image_dev
, 
 663         uint32_t msDelay 
= (131071 & random()); 
 664         HIBLOG("sleep %d\n", msDelay
); 
 667         clock_get_uptime(&endTime
); 
 668         SUB_ABSOLUTETIME(&endTime
, &startTime
); 
 669         absolutetime_to_nanoseconds(endTime
, &nsec
); 
 671         if (!vars
->fileRef
) err 
= kIOReturnNoSpace
; 
 674         if (kFSOpening 
!= gFSState
) err 
= kIOReturnTimeout
; 
 675         IOLockUnlock(gFSLock
); 
 677         HIBLOG("kern_open_file_for_direct_io(%d) took %qd ms\n", err
, nsec 
/ 1000000ULL); 
 678         if (kIOReturnSuccess 
!= err
) break; 
 680         if (kIOHibernateModeSSDInvert 
& gIOHibernateMode
) 
 681             vars
->flags 
^= kIOHibernateOptionSSD
; 
 683         HIBLOG("Opened file %s, size %qd, partition base 0x%qx, maxio %qx ssd %d\n", filename
, ctx
.size
,  
 684                     vars
->block0
, maxiobytes
, kIOHibernateOptionSSD 
& vars
->flags
); 
 685         if (ctx
.size 
< 1*1024*1024)             // check against image size estimate! 
 687             err 
= kIOReturnNoSpace
; 
 691         vars
->fileSize 
= ctx
.size
; 
 692         if (maxiobytes 
< vars
->bufferSize
) vars
->bufferSize 
= maxiobytes
; 
 694         vars
->extentMap 
= (IOPolledFileExtent 
*) extentsData
->getBytesNoCopy(); 
 696         part 
= IOCopyMediaForDev(block_dev
); 
 699             err 
= kIOReturnNotFound
; 
 702         err 
= part
->callPlatformFunction(PLATFORM_FUNCTION_GET_MEDIA_ENCRYPTION_KEY_UUID
, false,  
 703                                           (void *) &keyUUID
, (void *) &keyStoreUUID
, NULL
, NULL
); 
 704         if ((kIOReturnSuccess 
== err
) && keyUUID 
&& keyStoreUUID
) 
 706 //            IOLog("got volume key %s\n", keyStoreUUID->getCStringNoCopy()); 
 707             uuid_t                  volumeKeyUUID
; 
 708             aks_volume_key_t        vek
; 
 709             static IOService 
*      sKeyStore
; 
 710             static const OSSymbol 
* sAKSGetKey
; 
 713                 sAKSGetKey 
= OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY
); 
 715                 sKeyStore 
= (IOService 
*) IORegistryEntry::fromPath(AKS_SERVICE_PATH
, gIOServicePlane
); 
 717                 err 
= uuid_parse(keyStoreUUID
->getCStringNoCopy(), volumeKeyUUID
); 
 719                 err 
= kIOReturnNoResources
; 
 720             if (kIOReturnSuccess 
== err
)     
 721                 err 
= sKeyStore
->callPlatformFunction(sAKSGetKey
, true, volumeKeyUUID
, &vek
, NULL
, NULL
); 
 722             if (kIOReturnSuccess 
!= err
)     
 723                 IOLog("volume key err 0x%x\n", err
); 
 726                 size_t bytes 
= (kIOHibernateAESKeySize 
/ 8); 
 727                 if (vek
.key
.keybytecount 
< bytes
) 
 728                      bytes 
= vek
.key
.keybytecount
; 
 729                 bcopy(&vek
.key
.keybytes
[0], volumeCryptKey
, bytes
); 
 731             bzero(&vek
, sizeof(vek
)); 
 735         part 
= IOCopyMediaForDev(hibernate_image_dev
); 
 738             err 
= kIOReturnNotFound
; 
 742         IORegistryEntry 
* next
; 
 743         IORegistryEntry 
* child
; 
 746         vars
->pollers 
= OSArray::withCapacity(4); 
 749             err 
= kIOReturnNoMemory
; 
 753         vars
->blockSize 
= 512; 
 757             IOPolledInterface 
* poller
; 
 760             obj 
= next
->getProperty(kIOPolledInterfaceSupportKey
); 
 761             if (kOSBooleanFalse 
== obj
) 
 763                 vars
->pollers
->flushCollection(); 
 766             else if ((poller 
= OSDynamicCast(IOPolledInterface
, obj
))) 
 767                 vars
->pollers
->setObject(poller
); 
 768             if ((num 
= OSDynamicCast(OSNumber
, next
->getProperty(kIOMediaPreferredBlockSizeKey
)))) 
 769                 vars
->blockSize 
= num
->unsigned32BitValue(); 
 772         while ((next 
= child
->getParentEntry(gIOServicePlane
))  
 773                 && child
->isParent(next
, gIOServicePlane
, true)); 
 775         if (vars
->blockSize 
< 4096) vars
->blockSize 
= 4096; 
 777         HIBLOG("hibernate image major %d, minor %d, blocksize %ld, pollers %d\n", 
 778                     major(hibernate_image_dev
), minor(hibernate_image_dev
), (long)vars
->blockSize
, vars
->pollers
->getCount()); 
 780         if (vars
->pollers
->getCount() < kIOHibernateMinPollersNeeded
) 
 782             err 
= kIOReturnUnsupported
; 
 785         if (vars
->blockSize 
< sizeof(IOHibernateImageHeader
)) 
 787             err 
= kIOReturnError
; 
 791         err 
= IOHibernatePollerProbe(vars
, (IOService 
*) part
); 
 792         if (kIOReturnSuccess 
!= err
) break; 
 794         err 
= IOHibernatePollerOpen(vars
, kIOPolledPreflightState
, ioBuffer
); 
 795         if (kIOReturnSuccess 
!= err
) break; 
 801             next
->setProperty(kIOPolledInterfaceActiveKey
, kOSBooleanTrue
); 
 802             next 
= next
->getParentEntry(gIOServicePlane
); 
 806         *fileExtents 
= extentsData
; 
 810         if ((extentsData
->getLength() >= sizeof(IOPolledFileExtent
))) 
 812             char str2
[24 + sizeof(uuid_string_t
) + 2]; 
 814 #if defined(__i386__) || defined(__x86_64__) 
 815             if (!gIOCreateEFIDevicePathSymbol
) 
 816                 gIOCreateEFIDevicePathSymbol 
= OSSymbol::withCString("CreateEFIDevicePath"); 
 819                 snprintf(str2
, sizeof(str2
), "%qx:%s",  
 820                                 vars
->extentMap
[0].start
, keyUUID
->getCStringNoCopy()); 
 822                 snprintf(str2
, sizeof(str2
), "%qx", vars
->extentMap
[0].start
); 
 824             err 
= IOService::getPlatform()->callPlatformFunction( 
 825                                                 gIOCreateEFIDevicePathSymbol
, false, 
 826                                                 (void *) part
, (void *) str2
, 
 827                                                 (void *) (uintptr_t) true, (void *) &data
); 
 830             int len 
= sizeof(str1
); 
 832             if (!part
->getPath(str1
, &len
, gIODTPlane
)) 
 833                 err 
= kIOReturnNotFound
; 
 836                 snprintf(str2
, sizeof(str2
), ",%qx", vars
->extentMap
[0].start
); 
 837                 // (strip the plane name) 
 838                 char * tail 
= strchr(str1
, ':'); 
 841                 data 
= OSData::withBytes(tail 
+ 1, strlen(tail 
+ 1)); 
 842                 data
->appendBytes(str2
, strlen(str2
)); 
 845         if (kIOReturnSuccess 
== err
) 
 848             HIBLOG("error 0x%x getting path\n", err
); 
 853     if (kIOReturnSuccess 
!= err
) 
 855         HIBLOG("error 0x%x opening hibernation file\n", err
); 
 858             kern_close_file_for_direct_io(vars
->fileRef
, 0, 0, 0, 0, 0); 
 859             vars
->fileRef 
= NULL
; 
 870 IOPolledFileClose( IOPolledFileIOVars 
* vars 
) 
 874         IOHibernatePollerClose(vars
, kIOPolledPostflightState
); 
 875         vars
->pollers
->release(); 
 878     bzero(vars
, sizeof(IOPolledFileIOVars
)); 
 880     return (kIOReturnSuccess
); 
 884 IOPolledFileSeek(IOPolledFileIOVars 
* vars
, uint64_t position
) 
 886     IOPolledFileExtent 
* extentMap
; 
 888     extentMap 
= vars
->extentMap
; 
 890     vars
->position 
= position
; 
 892     while (position 
>= extentMap
->length
) 
 894         position 
-= extentMap
->length
; 
 898     vars
->currentExtent   
= extentMap
; 
 899     vars
->extentRemaining 
= extentMap
->length 
- position
; 
 900     vars
->extentPosition  
= vars
->position 
- position
; 
 902     if (vars
->bufferSize 
<= vars
->extentRemaining
) 
 903         vars
->bufferLimit 
= vars
->bufferSize
; 
 905         vars
->bufferLimit 
= vars
->extentRemaining
; 
 907     return (kIOReturnSuccess
); 
 911 IOPolledFileWrite(IOPolledFileIOVars 
* vars
, 
 912                     const uint8_t * bytes
, IOByteCount size
, 
 913                     hibernate_cryptvars_t 
* cryptvars
) 
 915     IOReturn    err 
= kIOReturnSuccess
; 
 923             // seek to end of block & flush 
 924             size 
= vars
->position 
& (vars
->blockSize 
- 1); 
 926                 size 
= vars
->blockSize 
- size
; 
 928             // use some garbage for the fill 
 929             bytes 
= vars
->buffer 
+ vars
->bufferOffset
; 
 932         copy 
= vars
->bufferLimit 
- vars
->bufferOffset
; 
 940             bcopy(bytes
, vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, copy
); 
 944             bzero(vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, copy
); 
 947         vars
->bufferOffset 
+= copy
; 
 948         vars
->position 
+= copy
; 
 950         if (flush 
&& vars
->bufferOffset
) 
 952             uint64_t offset 
= (vars
->position 
- vars
->bufferOffset 
 
 953                                 - vars
->extentPosition 
+ vars
->currentExtent
->start
); 
 954             uint32_t length 
= (vars
->bufferOffset
); 
 957             if (cryptvars 
&& vars
->encryptStart
 
 958                 && (vars
->position 
> vars
->encryptStart
) 
 959                 && ((vars
->position 
- length
) < vars
->encryptEnd
)) 
 961                 AbsoluteTime startTime
, endTime
; 
 963                 uint64_t encryptLen
, encryptStart
; 
 964                 encryptLen 
= vars
->position 
- vars
->encryptStart
; 
 965                 if (encryptLen 
> length
) 
 967                 encryptStart 
= length 
- encryptLen
; 
 968                 if (vars
->position 
> vars
->encryptEnd
) 
 969                     encryptLen 
-= (vars
->position 
- vars
->encryptEnd
); 
 971                 clock_get_uptime(&startTime
); 
 973                 // encrypt the buffer 
 974                 aes_encrypt_cbc(vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart
, 
 975                                 &cryptvars
->aes_iv
[0], 
 976                                 encryptLen 
/ AES_BLOCK_SIZE
, 
 977                                 vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart
, 
 978                                 &cryptvars
->ctx
.encrypt
); 
 980                 clock_get_uptime(&endTime
); 
 981                 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
); 
 982                 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
); 
 983                 vars
->cryptBytes 
+= encryptLen
; 
 985                 // save initial vector for following encrypts 
 986                 bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart 
+ encryptLen 
- AES_BLOCK_SIZE
, 
 987                         &cryptvars
->aes_iv
[0], 
 994                 err 
= IOHibernatePollerIODone(vars
, true); 
 995                 if (kIOReturnSuccess 
!= err
) 
 999 if (vars
->position 
& (vars
->blockSize 
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
); 
1000 //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length); 
1002             err 
= IOHibernatePollerIO(vars
, kIOPolledWrite
, vars
->bufferHalf
, offset
, length
); 
1003             if (kIOReturnSuccess 
!= err
) 
1007             vars
->extentRemaining 
-= vars
->bufferOffset
; 
1008             if (!vars
->extentRemaining
) 
1010                 vars
->currentExtent
++; 
1011                 vars
->extentRemaining 
= vars
->currentExtent
->length
; 
1012                 vars
->extentPosition  
= vars
->position
; 
1013                 if (!vars
->extentRemaining
) 
1015                     err 
= kIOReturnOverrun
; 
1020             vars
->bufferHalf 
= vars
->bufferHalf 
? 0 : vars
->bufferSize
; 
1021             vars
->bufferOffset 
= 0; 
1022             if (vars
->bufferSize 
<= vars
->extentRemaining
) 
1023                 vars
->bufferLimit 
= vars
->bufferSize
; 
1025                 vars
->bufferLimit 
= vars
->extentRemaining
; 
1036 IOPolledFileRead(IOPolledFileIOVars 
* vars
, 
1037                     uint8_t * bytes
, IOByteCount size
, 
1038                     hibernate_cryptvars_t 
* cryptvars
) 
1040     IOReturn    err 
= kIOReturnSuccess
; 
1043 //    bytesWritten += size; 
1047         copy 
= vars
->bufferLimit 
- vars
->bufferOffset
; 
1053             bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, bytes
, copy
); 
1057         vars
->bufferOffset 
+= copy
; 
1058 //      vars->position += copy; 
1060         if ((vars
->bufferOffset 
== vars
->bufferLimit
) && (vars
->position 
< vars
->readEnd
)) 
1064                 err 
= IOHibernatePollerIODone(vars
, false); 
1065                 if (kIOReturnSuccess 
!= err
) 
1071 if (vars
->position 
& (vars
->blockSize 
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
); 
1073             vars
->position        
+= vars
->lastRead
; 
1074             vars
->extentRemaining 
-= vars
->lastRead
; 
1075             vars
->bufferLimit      
= vars
->lastRead
; 
1077             if (!vars
->extentRemaining
) 
1079                 vars
->currentExtent
++; 
1080                 vars
->extentRemaining 
= vars
->currentExtent
->length
; 
1081                 vars
->extentPosition  
= vars
->position
; 
1082                 if (!vars
->extentRemaining
) 
1084                     err 
= kIOReturnOverrun
; 
1090             uint64_t lastReadLength 
= vars
->lastRead
; 
1091             uint64_t offset 
= (vars
->position 
 
1092                                 - vars
->extentPosition 
+ vars
->currentExtent
->start
); 
1093             if (vars
->extentRemaining 
<= vars
->bufferSize
) 
1094                 length 
= vars
->extentRemaining
; 
1096                 length 
= vars
->bufferSize
; 
1097             if ((length 
+ vars
->position
) > vars
->readEnd
) 
1098                 length 
= vars
->readEnd 
- vars
->position
; 
1100             vars
->lastRead 
= length
; 
1103 //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length); 
1104                 err 
= IOHibernatePollerIO(vars
, kIOPolledRead
, vars
->bufferHalf
, offset
, length
); 
1105                 if (kIOReturnSuccess 
!= err
) 
1110             vars
->bufferHalf 
= vars
->bufferHalf 
? 0 : vars
->bufferSize
; 
1111             vars
->bufferOffset 
= 0; 
1116                 uint8_t thisVector
[AES_BLOCK_SIZE
]; 
1117                 AbsoluteTime startTime
, endTime
; 
1119                 // save initial vector for following decrypts 
1120                 bcopy(&cryptvars
->aes_iv
[0], &thisVector
[0], AES_BLOCK_SIZE
); 
1121                 bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ lastReadLength 
- AES_BLOCK_SIZE
,  
1122                         &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
); 
1124                 // decrypt the buffer 
1125                 clock_get_uptime(&startTime
); 
1127                 aes_decrypt_cbc(vars
->buffer 
+ vars
->bufferHalf
, 
1129                                 lastReadLength 
/ AES_BLOCK_SIZE
, 
1130                                 vars
->buffer 
+ vars
->bufferHalf
, 
1131                                 &cryptvars
->ctx
.decrypt
); 
1133                 clock_get_uptime(&endTime
); 
1134                 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
); 
1135                 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
); 
1136                 vars
->cryptBytes 
+= lastReadLength
; 
1146 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1149 IOHibernateSystemSleep(void) 
1156     bool       dsSSD
, vmflush
; 
1157     IOHibernateVars 
* vars
; 
1159     gIOHibernateState 
= kIOHibernateStateInactive
; 
1161     if (!gIOChosenEntry
) 
1162         gIOChosenEntry 
= IORegistryEntry::fromPath("/chosen", gIODTPlane
); 
1164     gIOHibernateDebugFlags 
= 0; 
1165     if (kIOLogHibernate 
& gIOKitDebug
) 
1166         gIOHibernateDebugFlags 
|= kIOHibernateDebugRestoreLogs
; 
1168     if (IOService::getPMRootDomain()->getHibernateSettings( 
1169         &gIOHibernateMode
, &gIOHibernateFreeRatio
, &gIOHibernateFreeTime
)) 
1171         if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
1172             // default to discard clean for safe sleep 
1173             gIOHibernateMode 
^= (kIOHibernateModeDiscardCleanInactive 
 
1174                                 | kIOHibernateModeDiscardCleanActive
); 
1177     if ((obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey
))) 
1179         if ((str 
= OSDynamicCast(OSString
, obj
))) 
1180             strlcpy(gIOHibernateFilename
, str
->getCStringNoCopy(), 
1181                             sizeof(gIOHibernateFilename
)); 
1185     if (!gIOHibernateMode 
|| !gIOHibernateFilename
[0]) 
1186         return (kIOReturnUnsupported
); 
1188     HIBLOG("hibernate image path: %s\n", gIOHibernateFilename
); 
1190     vars 
= IONew(IOHibernateVars
, 1); 
1191     if (!vars
) return (kIOReturnNoMemory
); 
1192     bzero(vars
, sizeof(*vars
)); 
1194     IOLockLock(gFSLock
); 
1195     if (kFSIdle 
!= gFSState
) 
1197         HIBLOG("hibernate file busy\n"); 
1198         IOLockUnlock(gFSLock
); 
1199         IODelete(vars
, IOHibernateVars
, 1); 
1200         return (kIOReturnBusy
); 
1202     gFSState 
= kFSOpening
; 
1203     IOLockUnlock(gFSLock
); 
1207         vars
->srcBuffer 
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
, 
1208                                     2 * page_size 
+ WKdm_SCRATCH_BUF_SIZE
, page_size
); 
1209         vars
->ioBuffer  
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,  
1210                                     2 * kDefaultIOSize
, page_size
); 
1212         vars
->handoffBuffer 
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,  
1213                                     ptoa_64(gIOHibernateHandoffPageCount
), page_size
); 
1215         if (!vars
->srcBuffer 
|| !vars
->ioBuffer 
|| !vars
->handoffBuffer
) 
1217             err 
= kIOReturnNoMemory
; 
1221         if ((obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileMinSizeKey
))) 
1223             if ((num 
= OSDynamicCast(OSNumber
, obj
))) vars
->fileMinSize 
= num
->unsigned64BitValue(); 
1226         if ((obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileMaxSizeKey
))) 
1228             if ((num 
= OSDynamicCast(OSNumber
, obj
))) vars
->fileMaxSize 
= num
->unsigned64BitValue(); 
1232         boolean_t encryptedswap 
= true; 
1234         AbsoluteTime startTime
, endTime
; 
1237         bzero(gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
)); 
1238         gIOHibernateCurrentHeader
->debugFlags 
= gIOHibernateDebugFlags
; 
1239         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderInvalidSignature
; 
1241         vmflush 
= (kOSBooleanTrue 
== IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey
)); 
1242         uint64_t setFileSize 
= 0; 
1243         err 
= hibernate_alloc_page_lists(&vars
->page_list
,  
1244                                          &vars
->page_list_wired
, 
1245                                          &vars
->page_list_pal
); 
1246         if (KERN_SUCCESS 
!= err
) 
1249         if (vars
->fileMinSize 
|| (kIOHibernateModeFileResize 
& gIOHibernateMode
)) 
1251             hibernate_page_list_setall(vars
->page_list
, 
1252                                        vars
->page_list_wired
, 
1253                                        vars
->page_list_pal
, 
1254                                        true /* preflight */, 
1255                                        vmflush 
/* discard */, 
1257             PE_Video consoleInfo
; 
1258             bzero(&consoleInfo
, sizeof(consoleInfo
)); 
1259             IOService::getPlatform()->getConsoleInfo(&consoleInfo
); 
1261             // estimate: 5% increase in pages compressed 
1262             // screen preview 2 images compressed 50% 
1263             setFileSize 
= ((ptoa_64((105 * pageCount
) / 100) * gIOHibernateCompression
) >> 8) 
1264                                 + vars
->page_list
->list_size
 
1265                                 + (consoleInfo
.v_width 
* consoleInfo
.v_height 
* 4); 
1267             HIBLOG("hibernate_page_list_setall preflight pageCount %d est comp %qd setfile %qd min %qd\n",  
1268                     pageCount
, (100ULL * gIOHibernateCompression
) >> 8, 
1269                     setFileSize
, vars
->fileMinSize
); 
1271             if (!(kIOHibernateModeFileResize 
& gIOHibernateMode
) 
1272              && (setFileSize 
< vars
->fileMinSize
)) 
1274                 setFileSize 
= vars
->fileMinSize
; 
1278         // open & invalidate the image file 
1280         err 
= IOPolledFileOpen(gIOHibernateFilename
, setFileSize
, vars
->ioBuffer
, 
1281                                 &vars
->fileVars
, &vars
->fileExtents
, &data
,  
1282                                 &vars
->volumeCryptKey
[0]); 
1283         if (KERN_SUCCESS 
!= err
) 
1285             HIBLOG("IOPolledFileOpen(%x)\n", err
); 
1289         clock_get_uptime(&startTime
); 
1290         err 
= hibernate_setup(gIOHibernateCurrentHeader
,  
1291                                 gIOHibernateFreeRatio
, gIOHibernateFreeTime
, 
1293                                 vars
->page_list
, vars
->page_list_wired
, vars
->page_list_pal
); 
1294         clock_get_uptime(&endTime
); 
1295         SUB_ABSOLUTETIME(&endTime
, &startTime
); 
1296         absolutetime_to_nanoseconds(endTime
, &nsec
); 
1297         HIBLOG("hibernate_setup(%d) took %qd ms\n", err
, nsec 
/ 1000000ULL); 
1299         dsSSD 
= ((0 != (kIOHibernateOptionSSD 
& vars
->fileVars
->flags
)) 
1300                 && (kOSBooleanTrue 
== IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey
))); 
1303             gIOHibernateCurrentHeader
->options 
|=  
1304                                                 kIOHibernateOptionSSD
 
1305                                               | kIOHibernateOptionColor
; 
1307 #if defined(__i386__) || defined(__x86_64__) 
1308             if (!uuid_is_null(vars
->volumeCryptKey
) && 
1309                   (kOSBooleanTrue 
!= IOService::getPMRootDomain()->getProperty(kIOPMDestroyFVKeyOnStandbyKey
))) 
1311                 uintptr_t smcVars
[2]; 
1312                 smcVars
[0] = sizeof(vars
->volumeCryptKey
); 
1313                 smcVars
[1] = (uintptr_t)(void *) &gIOHibernateVars
.volumeCryptKey
[0]; 
1315                 IOService::getPMRootDomain()->setProperty(kIOHibernateSMCVariablesKey
, smcVars
, sizeof(smcVars
)); 
1316                 bzero(smcVars
, sizeof(smcVars
)); 
1322             gIOHibernateCurrentHeader
->options 
|= kIOHibernateOptionProgress
; 
1326         if (KERN_SUCCESS 
!= err
) 
1329         if (encryptedswap 
|| !uuid_is_null(vars
->volumeCryptKey
)) 
1330             gIOHibernateMode 
^= kIOHibernateModeEncrypt
;  
1332         if (kIOHibernateOptionProgress 
& gIOHibernateCurrentHeader
->options
) 
1334             vars
->videoAllocSize 
= kVideoMapSize
; 
1335             if (KERN_SUCCESS 
!= kmem_alloc_pageable(kernel_map
, &vars
->videoMapping
, vars
->videoAllocSize
)) 
1336                 vars
->videoMapping 
= 0; 
1339         // generate crypt keys 
1340         for (uint32_t i 
= 0; i 
< sizeof(vars
->wiredCryptKey
); i
++) 
1341             vars
->wiredCryptKey
[i
] = random(); 
1342         for (uint32_t i 
= 0; i 
< sizeof(vars
->cryptKey
); i
++) 
1343             vars
->cryptKey
[i
] = random(); 
1347         IORegistryEntry 
* regEntry
; 
1348         if (!gIOOptionsEntry
) 
1350             regEntry 
= IORegistryEntry::fromPath("/options", gIODTPlane
); 
1351             gIOOptionsEntry 
= OSDynamicCast(IODTNVRAM
, regEntry
); 
1352             if (regEntry 
&& !gIOOptionsEntry
) 
1353                 regEntry
->release(); 
1356         if (gIOOptionsEntry
) 
1358             const OSSymbol 
*  sym
; 
1360             sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey
); 
1363                 gIOOptionsEntry
->setProperty(sym
, data
); 
1368 #if defined(__i386__) || defined(__x86_64__) 
1369             struct AppleRTCHibernateVars
 
1371                 uint8_t     signature
[4]; 
1373                 uint8_t     booterSignature
[20]; 
1374                 uint8_t     wiredCryptKey
[16]; 
1376             AppleRTCHibernateVars rtcVars
; 
1378             rtcVars
.signature
[0] = 'A'; 
1379             rtcVars
.signature
[1] = 'A'; 
1380             rtcVars
.signature
[2] = 'P'; 
1381             rtcVars
.signature
[3] = 'L'; 
1382             rtcVars
.revision     
= 1; 
1383             bcopy(&vars
->wiredCryptKey
[0], &rtcVars
.wiredCryptKey
[0], sizeof(rtcVars
.wiredCryptKey
)); 
1384             if (gIOHibernateBootSignature
[0]) 
1388                 for (uint32_t i 
= 0; 
1389                     (c 
= gIOHibernateBootSignature
[i
]) && (i 
< (sizeof(rtcVars
.booterSignature
) << 1)); 
1400                     value 
= (value 
<< 4) | c
; 
1402                         rtcVars
.booterSignature
[i 
>> 1] = value
; 
1405             data 
= OSData::withBytes(&rtcVars
, sizeof(rtcVars
)); 
1408                 if (!gIOHibernateRTCVariablesKey
) 
1409                     gIOHibernateRTCVariablesKey 
= OSSymbol::withCStringNoCopy(kIOHibernateRTCVariablesKey
); 
1410                 if (gIOHibernateRTCVariablesKey
) 
1411                     IOService::getPMRootDomain()->setProperty(gIOHibernateRTCVariablesKey
, data
); 
1413                 if( gIOOptionsEntry 
) 
1415                     if( gIOHibernateMode 
& kIOHibernateModeSwitch 
) 
1417                         const OSSymbol 
*sym
; 
1418                         sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootSwitchVarsKey
); 
1421                             gIOOptionsEntry
->setProperty(sym
, data
); /* intentional insecure backup of rtc boot vars */ 
1431                 data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMachineSignatureKey
)); 
1433                     gIOHibernateCurrentHeader
->machineSignature 
= *((UInt32 
*)data
->getBytesNoCopy()); 
1437                     if (!gIOHibernateBoot0082Data
) 
1439                         data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty("boot-device-path")); 
1442                             // AppleNVRAM_EFI_LOAD_OPTION 
1444                                 uint32_t Attributes
; 
1445                                 uint16_t FilePathLength
; 
1448                             loadOptionHeader
.Attributes     
= 1; 
1449                             loadOptionHeader
.FilePathLength 
= data
->getLength(); 
1450                             loadOptionHeader
.Desc           
= 0; 
1451                             gIOHibernateBoot0082Data 
= OSData::withCapacity(sizeof(loadOptionHeader
) + loadOptionHeader
.FilePathLength
); 
1452                             if (gIOHibernateBoot0082Data
) 
1454                                 gIOHibernateBoot0082Data
->appendBytes(&loadOptionHeader
, sizeof(loadOptionHeader
)); 
1455                                 gIOHibernateBoot0082Data
->appendBytes(data
); 
1459                     if (!gIOHibernateBoot0082Key
) 
1460                         gIOHibernateBoot0082Key 
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:Boot0082"); 
1461                     if (!gIOHibernateBootNextKey
) 
1462                         gIOHibernateBootNextKey 
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:BootNext"); 
1463                     if (!gIOHibernateBootNextData
) 
1465                         uint16_t bits 
= 0x0082; 
1466                         gIOHibernateBootNextData 
= OSData::withBytes(&bits
, sizeof(bits
)); 
1468                     if (gIOHibernateBoot0082Key 
&& gIOHibernateBoot0082Data 
&& gIOHibernateBootNextKey 
&& gIOHibernateBootNextData
) 
1470                         gIOHibernateBootNextSave 
= gIOOptionsEntry
->copyProperty(gIOHibernateBootNextKey
); 
1471                         gIOOptionsEntry
->setProperty(gIOHibernateBoot0082Key
, gIOHibernateBoot0082Data
); 
1472                         gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextData
); 
1476 #else /* !i386 && !x86_64 */ 
1477             if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
1479                 data 
= OSData::withBytes(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
)); 
1480                 sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKeyKey
); 
1482                     gIOOptionsEntry
->setProperty(sym
, data
); 
1487                 if (false && gIOHibernateBootSignature
[0]) 
1489                     data 
= OSData::withCapacity(16); 
1490                     sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey
); 
1495                         for (uint32_t i 
= 0; (c 
= gIOHibernateBootSignature
[i
]); i
++) 
1505                             value 
= (value 
<< 4) | c
; 
1507                                 data
->appendBytes(&value
, sizeof(value
)); 
1509                         gIOOptionsEntry
->setProperty(sym
, data
); 
1517             if (!vars
->haveFastBoot
) 
1519                 // set boot volume to zero 
1520                 IODTPlatformExpert 
* platform 
= OSDynamicCast(IODTPlatformExpert
, IOService::getPlatform()); 
1521                 if (platform 
&& (kIOReturnSuccess 
== platform
->readXPRAM(kXPRamAudioVolume
,  
1522                                             &vars
->saveBootAudioVolume
, sizeof(vars
->saveBootAudioVolume
)))) 
1525                     newVolume 
= vars
->saveBootAudioVolume 
& 0xf8; 
1526                     platform
->writeXPRAM(kXPRamAudioVolume
,  
1527                                             &newVolume
, sizeof(newVolume
)); 
1530 #endif /* !i386 && !x86_64 */ 
1537     IOLockLock(gFSLock
); 
1538     if ((kIOReturnSuccess 
== err
) && (kFSOpening 
== gFSState
)) 
1540         gFSState 
= kFSOpened
; 
1541         gIOHibernateVars 
= *vars
; 
1542         gFileVars 
= *vars
->fileVars
; 
1543         gIOHibernateVars
.fileVars 
= &gFileVars
; 
1544         gIOHibernateFileRef 
= gFileVars
.fileRef
; 
1545         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderSignature
; 
1546         gIOHibernateState 
= kIOHibernateStateHibernating
; 
1550         HIBLOG("hibernate file close due timeout\n"); 
1551         if (vars
->fileVars 
&& vars
->fileVars
->fileRef
) kern_close_file_for_direct_io(vars
->fileVars
->fileRef
, 0, 0, 0, 0, 0); 
1552         IOHibernateDone(vars
); 
1555     IOLockUnlock(gFSLock
); 
1557     if (vars
->fileVars
) IODelete(vars
->fileVars
, IOPolledFileIOVars
, 1); 
1558     IODelete(vars
, IOHibernateVars
, 1); 
1563 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1565 DECLARE_IOHIBERNATEPROGRESSALPHA
 
1568 ProgressInit(hibernate_graphics_t 
* display
, uint8_t * screen
, uint8_t * saveunder
, uint32_t savelen
) 
1570     uint32_t    rowBytes
, pixelShift
; 
1573     uint32_t    alpha
, in
, color
, result
; 
1575     uint32_t    saveindex
[kIOHibernateProgressCount
] = { 0 }; 
1577     rowBytes 
= display
->rowBytes
; 
1578     pixelShift 
= display
->depth 
>> 4; 
1579     if (pixelShift 
< 1) return; 
1581     screen 
+= ((display
->width
 
1582                 - kIOHibernateProgressCount 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << (pixelShift 
- 1)) 
1583         + (display
->height 
- kIOHibernateProgressOriginY 
- kIOHibernateProgressHeight
) * rowBytes
; 
1585     for (y 
= 0; y 
< kIOHibernateProgressHeight
; y
++) 
1587         out 
= screen 
+ y 
* rowBytes
; 
1588         for (blob 
= 0; blob 
< kIOHibernateProgressCount
; blob
++) 
1590             color 
= blob 
? kIOHibernateProgressDarkGray 
: kIOHibernateProgressMidGray
; 
1591             for (x 
= 0; x 
< kIOHibernateProgressWidth
; x
++) 
1593                 alpha  
= gIOHibernateProgressAlpha
[y
][x
]; 
1599                         if (1 == pixelShift
) 
1601                             in 
= *((uint16_t *)out
) & 0x1f;     // 16 
1602                             in 
= (in 
<< 3) | (in 
>> 2); 
1605                             in 
= *((uint32_t *)out
) & 0xff;     // 32 
1606                         saveunder
[blob 
* kIOHibernateProgressSaveUnderSize 
+ saveindex
[blob
]++] = in
; 
1607                         result 
= ((255 - alpha
) * in 
+ alpha 
* result 
+ 0xff) >> 8; 
1609                     if (1 == pixelShift
) 
1612                         *((uint16_t *)out
) = (result 
<< 10) | (result 
<< 5) | result
;   // 16 
1615                         *((uint32_t *)out
) = (result 
<< 16) | (result 
<< 8) | result
;   // 32 
1617                 out 
+= (1 << pixelShift
); 
1619             out 
+= (kIOHibernateProgressSpacing 
<< pixelShift
); 
1626 ProgressUpdate(hibernate_graphics_t 
* display
, uint8_t * screen
, int32_t firstBlob
, int32_t select
) 
1628     uint32_t  rowBytes
, pixelShift
; 
1630     int32_t   blob
, lastBlob
; 
1631     uint32_t  alpha
, in
, color
, result
; 
1633     uint32_t  saveindex
[kIOHibernateProgressCount
] = { 0 }; 
1635     pixelShift 
= display
->depth 
>> 4; 
1639     rowBytes 
= display
->rowBytes
; 
1641     screen 
+= ((display
->width 
 
1642             - kIOHibernateProgressCount 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << (pixelShift 
- 1)) 
1643                 + (display
->height 
- kIOHibernateProgressOriginY 
- kIOHibernateProgressHeight
) * rowBytes
; 
1645     lastBlob  
= (select 
< kIOHibernateProgressCount
) ? select 
: (kIOHibernateProgressCount 
- 1); 
1647     screen 
+= (firstBlob 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << pixelShift
; 
1649     for (y 
= 0; y 
< kIOHibernateProgressHeight
; y
++) 
1651         out 
= screen 
+ y 
* rowBytes
; 
1652         for (blob 
= firstBlob
; blob 
<= lastBlob
; blob
++) 
1654             color 
= (blob 
< select
) ? kIOHibernateProgressLightGray 
: kIOHibernateProgressMidGray
; 
1655             for (x 
= 0; x 
< kIOHibernateProgressWidth
; x
++) 
1657                 alpha  
= gIOHibernateProgressAlpha
[y
][x
]; 
1663                         in 
= display
->progressSaveUnder
[blob
][saveindex
[blob
]++]; 
1664                         result 
= ((255 - alpha
) * in 
+ alpha 
* result 
+ 0xff) / 255; 
1666                     if (1 == pixelShift
) 
1669                         *((uint16_t *)out
) = (result 
<< 10) | (result 
<< 5) | result
;   // 16 
1672                         *((uint32_t *)out
) = (result 
<< 16) | (result 
<< 8) | result
;   // 32 
1674                 out 
+= (1 << pixelShift
); 
1676             out 
+= (kIOHibernateProgressSpacing 
<< pixelShift
); 
1681 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1684 IOHibernateIOKitSleep(void) 
1686     IOReturn ret 
= kIOReturnSuccess
; 
1687     IOLockLock(gFSLock
); 
1688     if (kFSOpening 
== gFSState
) 
1690         gFSState 
= kFSTimedOut
; 
1691         HIBLOG("hibernate file open timed out\n"); 
1692         ret 
= kIOReturnTimeout
; 
1694     IOLockUnlock(gFSLock
); 
1698 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1701 IOHibernateSystemHasSlept(void) 
1703     IOReturn          ret 
= kIOReturnSuccess
; 
1704     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
1708     IOLockLock(gFSLock
); 
1709     if ((kFSOpened 
!= gFSState
) && gIOHibernateMode
) 
1711         ret 
= kIOReturnTimeout
; 
1713     IOLockUnlock(gFSLock
); 
1714     if (kIOReturnSuccess 
!= ret
) return (ret
); 
1716     if (gIOHibernateMode
) obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernatePreviewBufferKey
); 
1717     vars
->previewBuffer 
= OSDynamicCast(IOMemoryDescriptor
, obj
); 
1718     if (obj 
&& !vars
->previewBuffer
) 
1721     vars
->consoleMapping 
= NULL
; 
1722     if (vars
->previewBuffer 
&& (kIOReturnSuccess 
!= vars
->previewBuffer
->prepare())) 
1724         vars
->previewBuffer
->release(); 
1725         vars
->previewBuffer 
= 0; 
1728     if ((kIOHibernateOptionProgress 
& gIOHibernateCurrentHeader
->options
) 
1729         && vars
->previewBuffer 
 
1730         && (data 
= OSDynamicCast(OSData
,  
1731         IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey
)))) 
1733         UInt32 flags 
= *((UInt32 
*)data
->getBytesNoCopy()); 
1734         HIBPRINT("kIOHibernatePreviewActiveKey %08lx\n", (long)flags
); 
1736         IOService::getPMRootDomain()->removeProperty(kIOHibernatePreviewActiveKey
); 
1738         if (kIOHibernatePreviewUpdates 
& flags
) 
1740             PE_Video           consoleInfo
; 
1741             hibernate_graphics_t 
* graphicsInfo 
= gIOHibernateGraphicsInfo
; 
1743             IOService::getPlatform()->getConsoleInfo(&consoleInfo
); 
1745             graphicsInfo
->width    
= consoleInfo
.v_width
; 
1746             graphicsInfo
->height   
= consoleInfo
.v_height
; 
1747             graphicsInfo
->rowBytes 
= consoleInfo
.v_rowBytes
; 
1748             graphicsInfo
->depth    
= consoleInfo
.v_depth
; 
1749             vars
->consoleMapping   
= (uint8_t *) consoleInfo
.v_baseAddr
; 
1751             HIBPRINT("video %p %d %d %d\n", 
1752                         vars
->consoleMapping
, graphicsInfo
->depth
,  
1753                         graphicsInfo
->width
, graphicsInfo
->height
); 
1754             if (vars
->consoleMapping
) 
1755                         ProgressInit(graphicsInfo
, vars
->consoleMapping
, 
1756                                         &graphicsInfo
->progressSaveUnder
[0][0], sizeof(graphicsInfo
->progressSaveUnder
)); 
1760     if (gIOOptionsEntry
) 
1761         gIOOptionsEntry
->sync(); 
1766 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1768 static DeviceTreeNode 
* 
1769 MergeDeviceTree(DeviceTreeNode 
* entry
, IORegistryEntry 
* regEntry
) 
1771     DeviceTreeNodeProperty 
* prop
; 
1772     DeviceTreeNode 
*         child
; 
1773     IORegistryEntry 
*        childRegEntry
; 
1774     const char *             nameProp
; 
1775     unsigned int             propLen
, idx
; 
1777     prop 
= (DeviceTreeNodeProperty 
*) (entry 
+ 1); 
1778     for (idx 
= 0; idx 
< entry
->nProperties
; idx
++) 
1780         if (regEntry 
&& (0 != strcmp("name", prop
->name
))) 
1782             regEntry
->setProperty((const char *) prop
->name
, (void *) (prop 
+ 1), prop
->length
); 
1783 //          HIBPRINT("%s: %s, %d\n", regEntry->getName(), prop->name, prop->length); 
1785         prop 
= (DeviceTreeNodeProperty 
*) (((uintptr_t)(prop 
+ 1)) + ((prop
->length 
+ 3) & ~3)); 
1788     child 
= (DeviceTreeNode 
*) prop
; 
1789     for (idx 
= 0; idx 
< entry
->nChildren
; idx
++) 
1791         if (kSuccess 
!= DTGetProperty(child
, "name", (void **) &nameProp
, &propLen
)) 
1793         childRegEntry 
= regEntry 
? regEntry
->childFromPath(nameProp
, gIODTPlane
) : NULL
; 
1794 //      HIBPRINT("%s == %p\n", nameProp, childRegEntry); 
1795         child 
= MergeDeviceTree(child
, childRegEntry
); 
1801 IOHibernateSystemWake(void) 
1803     if (kFSOpened 
== gFSState
) 
1805         IOHibernateDone(&gIOHibernateVars
); 
1809         IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey
); 
1810         IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey
); 
1812     return (kIOReturnSuccess
); 
1816 IOHibernateDone(IOHibernateVars 
* vars
) 
1818     IORegistryEntry 
* next
; 
1820     hibernate_teardown(vars
->page_list
, vars
->page_list_wired
, vars
->page_list_pal
); 
1822     if (vars
->videoMapping
) 
1824         if (vars
->videoMapSize
) 
1826             IOUnmapPages(kernel_map
, vars
->videoMapping
, vars
->videoMapSize
); 
1827         if (vars
->videoAllocSize
) 
1829             kmem_free(kernel_map
, trunc_page(vars
->videoMapping
), vars
->videoAllocSize
); 
1832     if (vars
->previewBuffer
) 
1834         vars
->previewBuffer
->release(); 
1835         vars
->previewBuffer 
= 0; 
1838     if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1840         IOService::getPMRootDomain()->setProperty(kIOHibernateOptionsKey
,  
1841                                             gIOHibernateCurrentHeader
->options
, 32); 
1845         IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey
); 
1848     if ((kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1849       && (kIOHibernateGfxStatusUnknown 
!= gIOHibernateGraphicsInfo
->gfxStatus
)) 
1851         IOService::getPMRootDomain()->setProperty(kIOHibernateGfxStatusKey
,  
1852                                         &gIOHibernateGraphicsInfo
->gfxStatus
, 
1853                                         sizeof(gIOHibernateGraphicsInfo
->gfxStatus
)); 
1857         IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey
); 
1862         if ((next 
= vars
->fileVars
->media
)) do 
1864             next
->removeProperty(kIOPolledInterfaceActiveKey
); 
1865             next 
= next
->getParentEntry(gIOServicePlane
); 
1868         IOPolledFileClose(vars
->fileVars
); 
1871     // invalidate nvram properties - (gIOOptionsEntry != 0) => nvram was touched 
1873 #if defined(__i386__) || defined(__x86_64__) 
1874         IOService::getPMRootDomain()->removeProperty(gIOHibernateRTCVariablesKey
); 
1875         IOService::getPMRootDomain()->removeProperty(kIOHibernateSMCVariablesKey
); 
1878          * Hibernate variable is written to NVRAM on platforms in which RtcRam 
1879          * is not backed by coin cell.  Remove Hibernate data from NVRAM. 
1881         if (gIOOptionsEntry
) { 
1883             if (gIOHibernateRTCVariablesKey
) { 
1884                 if (gIOOptionsEntry
->getProperty(gIOHibernateRTCVariablesKey
)) { 
1885                     gIOOptionsEntry
->removeProperty(gIOHibernateRTCVariablesKey
); 
1889             if (gIOHibernateBootNextKey
) 
1891                 if (gIOHibernateBootNextSave
) 
1893                     gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextSave
); 
1894                     gIOHibernateBootNextSave
->release(); 
1895                     gIOHibernateBootNextSave 
= NULL
; 
1898                     gIOOptionsEntry
->removeProperty(gIOHibernateBootNextKey
); 
1900             if (kIOHibernateStateWakingFromHibernate 
!= gIOHibernateState
) gIOOptionsEntry
->sync(); 
1904     if (vars
->srcBuffer
) 
1905         vars
->srcBuffer
->release(); 
1907         vars
->ioBuffer
->release(); 
1908     bzero(&gIOHibernateHandoffPages
[0], gIOHibernateHandoffPageCount 
* sizeof(gIOHibernateHandoffPages
[0])); 
1909     if (vars
->handoffBuffer
) 
1911         if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1913             IOHibernateHandoff 
* handoff
; 
1915             for (handoff 
= (IOHibernateHandoff 
*) vars
->handoffBuffer
->getBytesNoCopy(); 
1917                  handoff 
= (IOHibernateHandoff 
*) &handoff
->data
[handoff
->bytecount
]) 
1919                 HIBPRINT("handoff %p, %x, %x\n", handoff
, handoff
->type
, handoff
->bytecount
); 
1920                 uint8_t * data 
= &handoff
->data
[0]; 
1921                 switch (handoff
->type
) 
1923                     case kIOHibernateHandoffTypeEnd
: 
1927                     case kIOHibernateHandoffTypeDeviceTree
: 
1928                         MergeDeviceTree((DeviceTreeNode 
*) data
, IOService::getServiceRoot()); 
1931                     case kIOHibernateHandoffTypeKeyStore
: 
1932 #if defined(__i386__) || defined(__x86_64__) 
1934                             IOBufferMemoryDescriptor 
* 
1935                             md 
= IOBufferMemoryDescriptor::withBytes(data
, handoff
->bytecount
, kIODirectionOutIn
); 
1938                                 IOSetKeyStoreData(md
); 
1945                         done 
= (kIOHibernateHandoffType 
!= (handoff
->type 
& 0xFFFF0000)); 
1950         vars
->handoffBuffer
->release(); 
1952     if (vars
->fileExtents
) 
1953         vars
->fileExtents
->release(); 
1955     bzero(vars
, sizeof(*vars
)); 
1957 //    gIOHibernateState = kIOHibernateStateInactive;       // leave it for post wake code to see 
1959     return (kIOReturnSuccess
); 
1963 IOHibernateSystemPostWake(void) 
1965     struct kern_direct_file_io_ref_t 
* fileRef
; 
1967     if (kFSOpened 
== gFSState
) 
1969         // invalidate & close the image file 
1970         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderInvalidSignature
; 
1971         if ((fileRef 
= gIOHibernateFileRef
)) 
1973             gIOHibernateFileRef 
= 0; 
1974             IOSleep(TRIM_DELAY
); 
1975             kern_close_file_for_direct_io(fileRef
, 
1979                                        0, (caddr_t
) gIOHibernateCurrentHeader
,  
1980                                        sizeof(IOHibernateImageHeader
), 
1982                                        gIOHibernateCurrentHeader
->imageSize
); 
1987     return (kIOReturnSuccess
); 
1990 bool IOHibernateWasScreenLocked(void) 
1993     if ((kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) && gIOChosenEntry
) 
1996         data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOScreenLockStateKey
)); 
1997         if (data
) switch (*((uint32_t *)data
->getBytesNoCopy())) 
1999             case kIOScreenLockLocked
: 
2000             case kIOScreenLockFileVaultDialog
: 
2003             case kIOScreenLockNoLock
: 
2004             case kIOScreenLockUnlocked
: 
2013 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2015 SYSCTL_STRING(_kern
, OID_AUTO
, hibernatefile
,  
2016                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
2017                 gIOHibernateFilename
, sizeof(gIOHibernateFilename
), ""); 
2018 SYSCTL_STRING(_kern
, OID_AUTO
, bootsignature
,  
2019                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
2020                 gIOHibernateBootSignature
, sizeof(gIOHibernateBootSignature
), ""); 
2021 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatemode
,  
2022                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
2023                 &gIOHibernateMode
, 0, ""); 
2024 SYSCTL_STRUCT(_kern
, OID_AUTO
, hibernatestatistics
, 
2025                 CTLTYPE_STRUCT 
| CTLFLAG_RD 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
2026                 gIOHibernateStats
, hibernate_statistics_t
, ""); 
2028 SYSCTL_UINT(_kern
, OID_AUTO
, hibernategraphicsready
, 
2029                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_ANYBODY
, 
2030                 &gIOHibernateStats
->graphicsReadyTime
, 0, ""); 
2031 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatewakenotification
, 
2032                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_ANYBODY
, 
2033                 &gIOHibernateStats
->wakeNotificationTime
, 0, ""); 
2034 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatelockscreenready
, 
2035                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_ANYBODY
, 
2036                 &gIOHibernateStats
->lockScreenReadyTime
, 0, ""); 
2037 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatehidready
, 
2038                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_ANYBODY
, 
2039                 &gIOHibernateStats
->hidReadyTime
, 0, ""); 
2043 IOHibernateSystemInit(IOPMrootDomain 
* rootDomain
) 
2045     OSData 
* data 
= OSData::withBytesNoCopy(&gIOHibernateState
, sizeof(gIOHibernateState
)); 
2048         rootDomain
->setProperty(kIOHibernateStateKey
, data
); 
2052     if (PE_parse_boot_argn("hfile", gIOHibernateFilename
, sizeof(gIOHibernateFilename
))) 
2053         gIOHibernateMode 
= kIOHibernateModeOn
; 
2055         gIOHibernateFilename
[0] = 0; 
2057     sysctl_register_oid(&sysctl__kern_hibernatefile
); 
2058     sysctl_register_oid(&sysctl__kern_bootsignature
); 
2059     sysctl_register_oid(&sysctl__kern_hibernatemode
); 
2060     sysctl_register_oid(&sysctl__kern_hibernatestatistics
); 
2061     sysctl_register_oid(&sysctl__kern_hibernategraphicsready
); 
2062     sysctl_register_oid(&sysctl__kern_hibernatewakenotification
); 
2063     sysctl_register_oid(&sysctl__kern_hibernatelockscreenready
); 
2064     sysctl_register_oid(&sysctl__kern_hibernatehidready
); 
2066     gFSLock 
= IOLockAlloc(); 
2070 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2073 hibernate_setup_for_wake(void) 
2077 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2079 #define C_ASSERT(e) typedef char    __C_ASSERT__[(e) ? 1 : -1] 
2082 no_encrypt_page(vm_offset_t ppnum
) 
2084     if (pmap_is_noencrypt((ppnum_t
)ppnum
) == TRUE
) 
2092 hibernate_pal_callback(void *vars_arg
, vm_offset_t addr
) 
2094         IOHibernateVars 
*vars 
= (IOHibernateVars 
*)vars_arg
; 
2095         /* Make sure it's not in either of the save lists */ 
2096         hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
, atop_64(addr
), 1, kIOHibernatePageStateFree
); 
2098         /* Set it in the bitmap of pages owned by the PAL */ 
2099         hibernate_page_bitset(vars
->page_list_pal
, TRUE
, atop_64(addr
)); 
2102 static struct hibernate_cryptvars_t 
*local_cryptvars
; 
2105 hibernate_pal_write(void *buffer
, size_t size
) 
2107     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
2109         IOReturn err 
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *)buffer
, size
, local_cryptvars
); 
2110         if (kIOReturnSuccess 
!= err
) { 
2111                 kprintf("epic hibernate fail! %d\n", err
); 
2120 hibernate_write_image(void) 
2122     IOHibernateImageHeader 
* header 
= gIOHibernateCurrentHeader
; 
2123     IOHibernateVars 
*        vars  
= &gIOHibernateVars
; 
2124     IOPolledFileExtent 
*     fileExtents
; 
2126     C_ASSERT(sizeof(IOHibernateImageHeader
) == 512); 
2128     uint32_t     pageCount
, pagesDone
; 
2130     vm_offset_t  ppnum
, page
; 
2134     uint8_t *    compressed
; 
2136     void *       zerosCompressed
; 
2137     IOByteCount  pageCompressedSize
, zerosCompressedLen
; 
2138     uint64_t     compressedSize
, uncompressedSize
; 
2139     uint64_t     image1Size 
= 0; 
2140     uint32_t     bitmap_size
; 
2141     bool         iterDone
, pollerOpen
, needEncrypt
; 
2142     uint32_t     restore1Sum
, sum
, sum1
, sum2
; 
2146     uint32_t     pageAndCount
[2]; 
2150     AbsoluteTime startTime
, endTime
; 
2151     AbsoluteTime allTime
, compTime
; 
2154     uint32_t     lastProgressStamp 
= 0; 
2155     uint32_t     progressStamp
; 
2156     uint32_t     blob
, lastBlob 
= (uint32_t) -1L; 
2158     uint32_t     wiredPagesEncrypted
; 
2159     uint32_t     dirtyPagesEncrypted
; 
2160     uint32_t     wiredPagesClear
; 
2161     uint32_t     zeroPageCount
; 
2163     hibernate_cryptvars_t _cryptvars
; 
2164     hibernate_cryptvars_t 
* cryptvars 
= 0; 
2166     wiredPagesEncrypted 
= 0; 
2167     dirtyPagesEncrypted 
= 0; 
2168     wiredPagesClear     
= 0; 
2171     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers 
|| !vars
->fileExtents
) 
2172         return (false /* sleep */ ); 
2174     if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
2175         kdebug_enable 
= save_kdebug_enable
; 
2177     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_START
, 0, 0, 0, 0, 0); 
2178     IOService::getPMRootDomain()->tracePoint(kIOPMTracePointHibernate
); 
2180     restore1Sum 
= sum1 
= sum2 
= 0; 
2182     hibernate_pal_prepare(); 
2185     // encryption data. "iv" is the "initial vector". 
2186     if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2188         static const unsigned char first_iv
[AES_BLOCK_SIZE
] 
2189         = {  0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c, 
2190              0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda }; 
2192         cryptvars 
= &gIOHibernateCryptWakeContext
; 
2193         bzero(cryptvars
, sizeof(hibernate_cryptvars_t
)); 
2194         aes_encrypt_key(vars
->cryptKey
, 
2195                         kIOHibernateAESKeySize
, 
2196                         &cryptvars
->ctx
.encrypt
); 
2197         aes_decrypt_key(vars
->cryptKey
, 
2198                         kIOHibernateAESKeySize
, 
2199                         &cryptvars
->ctx
.decrypt
); 
2201         cryptvars 
= &_cryptvars
; 
2202         bzero(cryptvars
, sizeof(hibernate_cryptvars_t
)); 
2203         for (pageCount 
= 0; pageCount 
< sizeof(vars
->wiredCryptKey
); pageCount
++) 
2204             vars
->wiredCryptKey
[pageCount
] ^= vars
->volumeCryptKey
[pageCount
]; 
2205         bzero(&vars
->volumeCryptKey
[0], sizeof(vars
->volumeCryptKey
)); 
2206         aes_encrypt_key(vars
->wiredCryptKey
, 
2207                         kIOHibernateAESKeySize
, 
2208                         &cryptvars
->ctx
.encrypt
); 
2210         bcopy(&first_iv
[0], &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
); 
2211         bzero(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
)); 
2212         bzero(&vars
->cryptKey
[0], sizeof(vars
->cryptKey
)); 
2214         local_cryptvars 
= cryptvars
; 
2218     hibernate_setup_for_wake(); 
2220     hibernate_page_list_setall(vars
->page_list
, 
2221                                vars
->page_list_wired
, 
2222                                vars
->page_list_pal
, 
2223                                false /* !preflight */, 
2225                                ((0 == (kIOHibernateModeSleep 
& gIOHibernateMode
))  
2226                                && (0 != ((kIOHibernateModeDiscardCleanActive 
| kIOHibernateModeDiscardCleanInactive
) & gIOHibernateMode
))), 
2229     HIBLOG("hibernate_page_list_setall found pageCount %d\n", pageCount
); 
2231     fileExtents 
= (IOPolledFileExtent 
*) vars
->fileExtents
->getBytesNoCopy(); 
2234     count 
= vars
->fileExtents
->getLength() / sizeof(IOPolledFileExtent
); 
2235     for (page 
= 0; page 
< count
; page
++) 
2237         HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page
,  
2238                 fileExtents
[page
].start
, fileExtents
[page
].length
, 
2239                 fileExtents
[page
].start 
+ fileExtents
[page
].length
); 
2243     needEncrypt 
= (0 != (kIOHibernateModeEncrypt 
& gIOHibernateMode
)); 
2244     AbsoluteTime_to_scalar(&compTime
) = 0; 
2247     clock_get_uptime(&allTime
); 
2248     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2249                         kIOPMStatsHibernateImageWrite 
| kIOPMStatsEventStartFlag
, allTime
); 
2253         uncompressedSize 
= 0; 
2256         IOPolledFileSeek(vars
->fileVars
, vars
->fileVars
->blockSize
); 
2258         HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n",  
2259                 ml_get_interrupts_enabled()); 
2260         err 
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledBeforeSleepState
, vars
->ioBuffer
); 
2261         HIBLOG("IOHibernatePollerOpen(%x)\n", err
); 
2262         pollerOpen 
= (kIOReturnSuccess 
== err
); 
2266         // copy file block extent list if larger than header 
2268         count 
= vars
->fileExtents
->getLength(); 
2269         if (count 
> sizeof(header
->fileExtentMap
)) 
2271             count 
-= sizeof(header
->fileExtentMap
); 
2272             err 
= IOPolledFileWrite(vars
->fileVars
, 
2273                                     ((uint8_t *) &fileExtents
[0]) + sizeof(header
->fileExtentMap
), count
, cryptvars
); 
2274             if (kIOReturnSuccess 
!= err
) 
2278         uintptr_t hibernateBase
; 
2279         uintptr_t hibernateEnd
; 
2281         hibernateBase 
= HIB_BASE
; /* Defined in PAL headers */ 
2283         hibernateEnd 
= (segHIBB 
+ segSizeHIB
); 
2285         // copy out restore1 code 
2288             (phys64 
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2291             for (pagesDone 
= 0; pagesDone 
< atop_32(segLen
); pagesDone
++) 
2293                 gIOHibernateHandoffPages
[atop_32(count
) + pagesDone
] = atop_64(phys64
) + pagesDone
; 
2297         page 
= atop_32(kvtophys(hibernateBase
)); 
2298         count 
= atop_32(round_page(hibernateEnd
) - hibernateBase
); 
2299         header
->restore1CodePhysPage 
= page
; 
2300         header
->restore1CodeVirt 
= hibernateBase
; 
2301         header
->restore1PageCount 
= count
; 
2302         header
->restore1CodeOffset 
= ((uintptr_t) &hibernate_machine_entrypoint
)      - hibernateBase
; 
2303         header
->restore1StackOffset 
= ((uintptr_t) &gIOHibernateRestoreStackEnd
[0]) - 64 - hibernateBase
; 
2305         // sum __HIB seg, with zeros for the stack 
2306         src 
= (uint8_t *) trunc_page(hibernateBase
); 
2307         for (page 
= 0; page 
< count
; page
++) 
2309             if ((src 
< &gIOHibernateRestoreStack
[0]) || (src 
>= &gIOHibernateRestoreStackEnd
[0])) 
2310                 restore1Sum 
+= hibernate_sum_page(src
, header
->restore1CodeVirt 
+ page
); 
2312                 restore1Sum 
+= 0x00000000; 
2317         // write the __HIB seg, with zeros for the stack 
2319         src 
= (uint8_t *) trunc_page(hibernateBase
); 
2320         count 
= ((uintptr_t) &gIOHibernateRestoreStack
[0]) - trunc_page(hibernateBase
); 
2323             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2324             if (kIOReturnSuccess 
!= err
) 
2327         err 
= IOPolledFileWrite(vars
->fileVars
,  
2329                                         &gIOHibernateRestoreStackEnd
[0] - &gIOHibernateRestoreStack
[0], 
2331         if (kIOReturnSuccess 
!= err
) 
2333         src 
= &gIOHibernateRestoreStackEnd
[0]; 
2334         count 
= round_page(hibernateEnd
) - ((uintptr_t) src
); 
2337             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2338             if (kIOReturnSuccess 
!= err
) 
2342         if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2344             vars
->fileVars
->encryptStart 
= (vars
->fileVars
->position 
& ~(AES_BLOCK_SIZE 
- 1)); 
2345             vars
->fileVars
->encryptEnd   
= UINT64_MAX
; 
2346             HIBLOG("encryptStart %qx\n", vars
->fileVars
->encryptStart
); 
2349         // write the preview buffer 
2351         if (vars
->previewBuffer
) 
2357                 phys64 
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
); 
2358                 pageAndCount
[0] = atop_64(phys64
); 
2359                 pageAndCount
[1] = atop_32(segLen
); 
2360                 err 
= IOPolledFileWrite(vars
->fileVars
,  
2361                                         (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),  
2363                 if (kIOReturnSuccess 
!= err
) 
2366                 ppnum 
+= sizeof(pageAndCount
); 
2369             if (kIOReturnSuccess 
!= err
) 
2372             src 
= (uint8_t *) vars
->previewBuffer
->getPhysicalSegment(0, NULL
, _kIOMemorySourceSegment
); 
2374                         ((hibernate_preview_t 
*)src
)->lockTime 
= gIOConsoleLockTime
; 
2376             count 
= vars
->previewBuffer
->getLength(); 
2378             header
->previewPageListSize 
= ppnum
; 
2379             header
->previewSize 
= count 
+ ppnum
; 
2381             for (page 
= 0; page 
< count
; page 
+= page_size
) 
2383                 phys64 
= vars
->previewBuffer
->getPhysicalSegment(page
, NULL
, kIOMemoryMapperNone
); 
2384                 sum1 
+= hibernate_sum_page(src 
+ page
, atop_64(phys64
)); 
2386             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2387             if (kIOReturnSuccess 
!= err
) 
2391         // mark areas for no save 
2394             (phys64 
= vars
->ioBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2397             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2398                                         atop_64(phys64
), atop_32(segLen
), 
2399                                         kIOHibernatePageStateFree
); 
2400             pageCount 
-= atop_32(segLen
); 
2404             (phys64 
= vars
->srcBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2407             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2408                                         atop_64(phys64
), atop_32(segLen
), 
2409                                         kIOHibernatePageStateFree
); 
2410             pageCount 
-= atop_32(segLen
); 
2413         // copy out bitmap of pages available for trashing during restore 
2415         bitmap_size 
= vars
->page_list_wired
->list_size
; 
2416         src 
= (uint8_t *) vars
->page_list_wired
; 
2417         err 
= IOPolledFileWrite(vars
->fileVars
, src
, bitmap_size
, cryptvars
); 
2418         if (kIOReturnSuccess 
!= err
) 
2421         // mark more areas for no save, but these are not available  
2422         // for trashing during restore 
2424         hibernate_page_list_set_volatile(vars
->page_list
, vars
->page_list_wired
, &pageCount
); 
2427         page 
= atop_32(KERNEL_IMAGE_TO_PHYS(hibernateBase
)); 
2428         count 
= atop_32(round_page(KERNEL_IMAGE_TO_PHYS(hibernateEnd
))) - page
; 
2429         hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
, 
2431                                         kIOHibernatePageStateFree
); 
2434         if (vars
->previewBuffer
) for (count 
= 0; 
2435                                         (phys64 
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2438             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2439                                         atop_64(phys64
), atop_32(segLen
), 
2440                                         kIOHibernatePageStateFree
); 
2441             pageCount 
-= atop_32(segLen
); 
2445             (phys64 
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2448             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2449                                         atop_64(phys64
), atop_32(segLen
), 
2450                                         kIOHibernatePageStateFree
); 
2451             pageCount 
-= atop_32(segLen
); 
2454                 (void)hibernate_pal_callback
; 
2456         src 
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy(); 
2457         compressed 
= src 
+ page_size
; 
2458         scratch    
= compressed 
+ page_size
; 
2460         // compress a zero page 
2461         bzero(src
, page_size
); 
2462         zerosCompressed    
= vars
->handoffBuffer
->getBytesNoCopy(); 
2463         zerosCompressedLen 
= WKdm_compress_new((WK_word
*) src
, 
2464                                                (WK_word
*) zerosCompressed
,  
2471         HIBLOG("bitmap_size 0x%x, previewSize 0x%x, writing %d pages @ 0x%llx\n",  
2472                 bitmap_size
, header
->previewSize
, 
2473                 pageCount
, vars
->fileVars
->position
); 
2480             kWiredEncrypt   
= kWired 
| kEncrypt
, 
2481             kWiredClear     
= kWired
, 
2482             kUnwiredEncrypt 
= kEncrypt
 
2485         for (pageType 
= kWiredEncrypt
; pageType 
>= kUnwiredEncrypt
; pageType
--) 
2487             if (kUnwiredEncrypt 
== pageType
) 
2489                 // start unwired image 
2490                 if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2492                     vars
->fileVars
->encryptStart 
= (vars
->fileVars
->position 
& ~(((uint64_t)AES_BLOCK_SIZE
) - 1)); 
2493                     vars
->fileVars
->encryptEnd   
= UINT64_MAX
; 
2494                     HIBLOG("encryptStart %qx\n", vars
->fileVars
->encryptStart
); 
2496                 bcopy(&cryptvars
->aes_iv
[0],  
2497                         &gIOHibernateCryptWakeContext
.aes_iv
[0],  
2498                         sizeof(cryptvars
->aes_iv
)); 
2499                 cryptvars 
= &gIOHibernateCryptWakeContext
; 
2501             for (iterDone 
= false, ppnum 
= 0; !iterDone
; ) 
2503                 count 
= hibernate_page_list_iterate((kWired 
& pageType
)  
2504                                                             ? vars
->page_list_wired 
: vars
->page_list
, 
2506 //              kprintf("[%d](%x : %x)\n", pageType, ppnum, count); 
2509                 if (count 
&& (kWired 
& pageType
) && needEncrypt
) 
2511                     uint32_t checkIndex
; 
2512                     for (checkIndex 
= 0; 
2513                             (checkIndex 
< count
)  
2514                                 && (((kEncrypt 
& pageType
) == 0) == no_encrypt_page(ppnum 
+ checkIndex
));  
2527                     case kWiredEncrypt
:   wiredPagesEncrypted 
+= count
; break; 
2528                     case kWiredClear
:     wiredPagesClear     
+= count
; break; 
2529                     case kUnwiredEncrypt
: dirtyPagesEncrypted 
+= count
; break; 
2532                 if (iterDone 
&& (kWiredEncrypt 
== pageType
))   {/* not yet end of wired list */} 
2535                     pageAndCount
[0] = ppnum
; 
2536                     pageAndCount
[1] = count
; 
2537                     err 
= IOPolledFileWrite(vars
->fileVars
,  
2538                                             (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),  
2540                     if (kIOReturnSuccess 
!= err
) 
2544                 for (page 
= ppnum
; page 
< (ppnum 
+ count
); page
++) 
2546                     err 
= IOMemoryDescriptorWriteFromPhysical(vars
->srcBuffer
, 0, ptoa_64(page
), page_size
); 
2549                         HIBLOG("IOMemoryDescriptorWriteFromPhysical %d [%ld] %x\n", __LINE__
, (long)page
, err
); 
2553                     sum 
= hibernate_sum_page(src
, page
); 
2554                     if (kWired 
& pageType
) 
2559                     clock_get_uptime(&startTime
); 
2560                     wkresult 
= WKdm_compress_new((WK_word
*) src
, 
2561                                                  (WK_word
*) compressed
,  
2565                     clock_get_uptime(&endTime
); 
2566                     ADD_ABSOLUTETIME(&compTime
, &endTime
); 
2567                     SUB_ABSOLUTETIME(&compTime
, &startTime
); 
2569                     compBytes 
+= page_size
; 
2570                     pageCompressedSize 
= (-1 == wkresult
) ? page_size 
: wkresult
; 
2572                     if ((pageCompressedSize 
== zerosCompressedLen
)  
2573                      && !bcmp(compressed
, zerosCompressed
, zerosCompressedLen
)) 
2575                         pageCompressedSize 
= 0; 
2579                     if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2580                         pageCompressedSize 
= (pageCompressedSize 
+ AES_BLOCK_SIZE 
- 1) & ~(AES_BLOCK_SIZE 
- 1); 
2582                     if (pageCompressedSize 
!= page_size
) 
2587                     tag 
= pageCompressedSize 
| kIOHibernateTagSignature
; 
2588                     err 
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *) &tag
, sizeof(tag
), cryptvars
); 
2589                     if (kIOReturnSuccess 
!= err
) 
2592                     err 
= IOPolledFileWrite(vars
->fileVars
, data
, (pageCompressedSize 
+ 3) & ~3, cryptvars
); 
2593                     if (kIOReturnSuccess 
!= err
) 
2596                     compressedSize 
+= pageCompressedSize
; 
2597                     uncompressedSize 
+= page_size
; 
2600                     if (vars
->consoleMapping 
&& (0 == (1023 & pagesDone
))) 
2602                         blob 
= ((pagesDone 
* kIOHibernateProgressCount
) / pageCount
); 
2603                         if (blob 
!= lastBlob
) 
2605                             ProgressUpdate(gIOHibernateGraphicsInfo
, vars
->consoleMapping
, lastBlob
, blob
); 
2609                     if (0 == (8191 & pagesDone
)) 
2611                         clock_get_uptime(&endTime
); 
2612                         SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2613                         absolutetime_to_nanoseconds(endTime
, &nsec
); 
2614                         progressStamp 
= nsec 
/ 750000000ULL; 
2615                         if (progressStamp 
!= lastProgressStamp
) 
2617                             lastProgressStamp 
= progressStamp
; 
2618                             HIBPRINT("pages %d (%d%%)\n", pagesDone
, (100 * pagesDone
) / pageCount
); 
2622                 if (kIOReturnSuccess 
!= err
) 
2627             if (kIOReturnSuccess 
!= err
) 
2630             if ((kEncrypt 
& pageType
) && vars
->fileVars
->encryptStart
) 
2632                 vars
->fileVars
->encryptEnd 
= ((vars
->fileVars
->position 
+ 511) & ~511ULL); 
2633                 HIBLOG("encryptEnd %qx\n", vars
->fileVars
->encryptEnd
); 
2636             if (kWiredEncrypt 
!= pageType
) 
2638                 // end of image1/2 - fill to next block 
2639                 err 
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
); 
2640                 if (kIOReturnSuccess 
!= err
) 
2643             if (kWiredClear 
== pageType
) 
2645                 // enlarge wired image for test 
2646 //              err = IOPolledFileWrite(vars->fileVars, 0, 0x60000000, cryptvars); 
2649                 header
->encryptStart 
= vars
->fileVars
->encryptStart
; 
2650                 header
->encryptEnd   
= vars
->fileVars
->encryptEnd
; 
2651                 image1Size 
= vars
->fileVars
->position
; 
2652                 HIBLOG("image1Size 0x%qx, encryptStart1 0x%qx, End1 0x%qx\n", 
2653                         image1Size
, header
->encryptStart
, header
->encryptEnd
); 
2656         if (kIOReturnSuccess 
!= err
) 
2661         header
->imageSize    
= vars
->fileVars
->position
; 
2662         header
->image1Size   
= image1Size
; 
2663         header
->bitmapSize   
= bitmap_size
; 
2664         header
->pageCount    
= pageCount
; 
2666         header
->restore1Sum  
= restore1Sum
; 
2667         header
->image1Sum    
= sum1
; 
2668         header
->image2Sum    
= sum2
; 
2669         header
->sleepTime    
= gIOLastSleepTime
.tv_sec
; 
2671         header
->compression     
= (compressedSize 
<< 8) / uncompressedSize
; 
2672         gIOHibernateCompression 
= header
->compression
; 
2674         count 
= vars
->fileExtents
->getLength(); 
2675         if (count 
> sizeof(header
->fileExtentMap
)) 
2677             header
->fileExtentMapSize 
= count
; 
2678             count 
= sizeof(header
->fileExtentMap
); 
2681             header
->fileExtentMapSize 
= sizeof(header
->fileExtentMap
); 
2682         bcopy(&fileExtents
[0], &header
->fileExtentMap
[0], count
); 
2684         header
->deviceBase      
= vars
->fileVars
->block0
; 
2685         header
->deviceBlockSize 
= vars
->fileVars
->blockSize
; 
2687         IOPolledFileSeek(vars
->fileVars
, 0); 
2688         err 
= IOPolledFileWrite(vars
->fileVars
, 
2689                                     (uint8_t *) header
, sizeof(IOHibernateImageHeader
),  
2691         if (kIOReturnSuccess 
!= err
) 
2693         err 
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
); 
2694         if (kIOReturnSuccess 
!= err
) 
2696         err 
= IOHibernatePollerIODone(vars
->fileVars
, true); 
2697         if (kIOReturnSuccess 
!= err
) 
2702     clock_get_uptime(&endTime
); 
2704     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2705                         kIOPMStatsHibernateImageWrite 
| kIOPMStatsEventStopFlag
, endTime
); 
2707     SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2708     absolutetime_to_nanoseconds(endTime
, &nsec
); 
2709     HIBLOG("all time: %qd ms, ", nsec 
/ 1000000ULL); 
2711     absolutetime_to_nanoseconds(compTime
, &nsec
); 
2712     HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",  
2715                 nsec 
? (((compBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2717     absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
); 
2718     HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s, ",  
2719                 vars
->fileVars
->cryptBytes
,  
2721                 nsec 
? (((vars
->fileVars
->cryptBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2723     HIBLOG("\nimage %qd (%lld%%), uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n",  
2724                header
->imageSize
, (header
->imageSize 
* 100) / vars
->fileVars
->fileSize
, 
2725                uncompressedSize
, atop_32(uncompressedSize
), compressedSize
, 
2726                uncompressedSize 
? ((int) ((compressedSize 
* 100ULL) / uncompressedSize
)) : 0, 
2729     HIBLOG("zeroPageCount %d, wiredPagesEncrypted %d, wiredPagesClear %d, dirtyPagesEncrypted %d\n",  
2730              zeroPageCount
, wiredPagesEncrypted
, wiredPagesClear
, dirtyPagesEncrypted
); 
2732     if (vars
->fileVars
->io
) 
2733         (void) IOHibernatePollerIODone(vars
->fileVars
, false); 
2736         IOHibernatePollerClose(vars
->fileVars
, kIOPolledBeforeSleepState
); 
2738     if (vars
->consoleMapping
) 
2739         ProgressUpdate(gIOHibernateGraphicsInfo
,  
2740                         vars
->consoleMapping
, 0, kIOHibernateProgressCount
); 
2742     HIBLOG("hibernate_write_image done(%x)\n", err
); 
2744     // should we come back via regular wake, set the state in memory. 
2745     gIOHibernateState 
= kIOHibernateStateInactive
; 
2747     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_END
, 
2748                           wiredPagesEncrypted
, wiredPagesClear
, dirtyPagesEncrypted
, 0, 0); 
2750     if (kIOReturnSuccess 
== err
) 
2752         if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
2754             return (kIOHibernatePostWriteSleep
); 
2756         else if(kIOHibernateModeRestart 
& gIOHibernateMode
) 
2758             return (kIOHibernatePostWriteRestart
); 
2762             /* by default, power down */ 
2763             return (kIOHibernatePostWriteHalt
); 
2766     else if (kIOReturnAborted 
== err
) 
2768         return (kIOHibernatePostWriteWake
); 
2772         /* on error, sleep */ 
2773         return (kIOHibernatePostWriteSleep
); 
2777 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2780 hibernate_machine_init(void) 
2785     uint32_t     pagesRead 
= 0; 
2786     AbsoluteTime startTime
, compTime
; 
2787     AbsoluteTime allTime
, endTime
; 
2788     AbsoluteTime startIOTime
, endIOTime
; 
2789     uint64_t     nsec
, nsecIO
; 
2791     uint32_t     lastProgressStamp 
= 0; 
2792     uint32_t     progressStamp
; 
2793     hibernate_cryptvars_t 
* cryptvars 
= 0; 
2795     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
2796     bzero(gIOHibernateStats
, sizeof(hibernate_statistics_t
)); 
2798     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers 
|| !vars
->fileExtents
) 
2801     sum 
= gIOHibernateCurrentHeader
->actualImage1Sum
; 
2802     pagesDone 
= gIOHibernateCurrentHeader
->actualUncompressedPages
; 
2804     if (kIOHibernateStateWakingFromHibernate 
!= gIOHibernateState
) 
2806         HIBLOG("regular wake\n"); 
2810     HIBPRINT("diag %x %x %x %x\n", 
2811             gIOHibernateCurrentHeader
->diag
[0], gIOHibernateCurrentHeader
->diag
[1],  
2812             gIOHibernateCurrentHeader
->diag
[2], gIOHibernateCurrentHeader
->diag
[3]); 
2814 #define t40ms(x)        (tmrCvt((((uint64_t)(x)) << 8), tscFCvtt2n) / 1000000) 
2815 #define tStat(x, y)     gIOHibernateStats->x = t40ms(gIOHibernateCurrentHeader->y); 
2816     tStat(booterStart
, booterStart
); 
2817     gIOHibernateStats
->smcStart 
= gIOHibernateCurrentHeader
->smcStart
, 
2818     tStat(booterDuration0
, booterTime0
); 
2819     tStat(booterDuration1
, booterTime1
); 
2820     tStat(booterDuration2
, booterTime2
); 
2821     tStat(booterDuration
, booterTime
); 
2822     tStat(booterConnectDisplayDuration
, connectDisplayTime
); 
2823     tStat(booterSplashDuration
, splashTime
); 
2824     tStat(trampolineDuration
, trampolineTime
); 
2826     gIOHibernateStats
->image1Size  
= gIOHibernateCurrentHeader
->image1Size
; 
2827     gIOHibernateStats
->imageSize   
= gIOHibernateCurrentHeader
->imageSize
; 
2828     gIOHibernateStats
->image1Pages 
= pagesDone
; 
2830     HIBLOG("booter start at %d ms smc %d ms, [%d, %d, %d] total %d ms, dsply %d, %d ms, tramp %d ms\n",  
2831            gIOHibernateStats
->booterStart
, 
2832            gIOHibernateStats
->smcStart
, 
2833            gIOHibernateStats
->booterDuration0
, 
2834            gIOHibernateStats
->booterDuration1
, 
2835            gIOHibernateStats
->booterDuration2
, 
2836            gIOHibernateStats
->booterDuration
, 
2837            gIOHibernateStats
->booterConnectDisplayDuration
, 
2838            gIOHibernateStats
->booterSplashDuration
, 
2839            gIOHibernateStats
->trampolineDuration
); 
2841     HIBLOG("hibernate_machine_init: state %d, image pages %d, sum was %x, imageSize 0x%qx, image1Size 0x%qx, conflictCount %d, nextFree %x\n", 
2842             gIOHibernateState
, pagesDone
, sum
, gIOHibernateStats
->imageSize
, gIOHibernateStats
->image1Size
, 
2843             gIOHibernateCurrentHeader
->conflictCount
, gIOHibernateCurrentHeader
->nextFree
); 
2845     if ((0 != (kIOHibernateModeSleep 
& gIOHibernateMode
))  
2846      && (0 != ((kIOHibernateModeDiscardCleanActive 
| kIOHibernateModeDiscardCleanInactive
) & gIOHibernateMode
))) 
2848         hibernate_page_list_discard(vars
->page_list
); 
2851     cryptvars 
= (kIOHibernateModeEncrypt 
& gIOHibernateMode
) ? &gIOHibernateCryptWakeContext 
: 0; 
2853     if (gIOHibernateCurrentHeader
->handoffPageCount 
> gIOHibernateHandoffPageCount
) 
2854         panic("handoff overflow"); 
2856     IOHibernateHandoff 
* handoff
; 
2858     bool                 foundCryptData 
= false; 
2860     for (handoff 
= (IOHibernateHandoff 
*) vars
->handoffBuffer
->getBytesNoCopy(); 
2862          handoff 
= (IOHibernateHandoff 
*) &handoff
->data
[handoff
->bytecount
]) 
2864 //      HIBPRINT("handoff %p, %x, %x\n", handoff, handoff->type, handoff->bytecount); 
2865         uint8_t * data 
= &handoff
->data
[0]; 
2866         switch (handoff
->type
) 
2868             case kIOHibernateHandoffTypeEnd
: 
2872             case kIOHibernateHandoffTypeGraphicsInfo
: 
2873                 bcopy(data
, gIOHibernateGraphicsInfo
, sizeof(*gIOHibernateGraphicsInfo
)); 
2876             case kIOHibernateHandoffTypeCryptVars
: 
2879                     hibernate_cryptwakevars_t 
* 
2880                     wakevars 
= (hibernate_cryptwakevars_t 
*) &handoff
->data
[0]; 
2881                     bcopy(&wakevars
->aes_iv
[0], &cryptvars
->aes_iv
[0], sizeof(cryptvars
->aes_iv
)); 
2883                 foundCryptData 
= true; 
2884                 bzero(data
, handoff
->bytecount
); 
2887             case kIOHibernateHandoffTypeMemoryMap
: 
2889                 clock_get_uptime(&allTime
); 
2891                 hibernate_newruntime_map(data
, handoff
->bytecount
,  
2892                                          gIOHibernateCurrentHeader
->systemTableOffset
); 
2894                 clock_get_uptime(&endTime
); 
2896                 SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2897                 absolutetime_to_nanoseconds(endTime
, &nsec
); 
2899                 HIBLOG("hibernate_newruntime_map time: %qd ms, ", nsec 
/ 1000000ULL); 
2903             case kIOHibernateHandoffTypeDeviceTree
: 
2905 //                  DTEntry chosen = NULL; 
2906 //                  HIBPRINT("DTLookupEntry %d\n", DTLookupEntry((const DTEntry) data, "/chosen", &chosen)); 
2911                 done 
= (kIOHibernateHandoffType 
!= (handoff
->type 
& 0xFFFF0000)); 
2915     if (cryptvars 
&& !foundCryptData
) 
2916         panic("hibernate handoff"); 
2918     HIBPRINT("video %x %d %d %d status %x\n", 
2919             gIOHibernateGraphicsInfo
->physicalAddress
, gIOHibernateGraphicsInfo
->depth
,  
2920             gIOHibernateGraphicsInfo
->width
, gIOHibernateGraphicsInfo
->height
, gIOHibernateGraphicsInfo
->gfxStatus
);  
2922     if (vars
->videoMapping 
&& gIOHibernateGraphicsInfo
->physicalAddress
) 
2924         vars
->videoMapSize 
= round_page(gIOHibernateGraphicsInfo
->height 
 
2925                                         * gIOHibernateGraphicsInfo
->rowBytes
); 
2926         IOMapPages(kernel_map
,  
2927                     vars
->videoMapping
, gIOHibernateGraphicsInfo
->physicalAddress
, 
2928                     vars
->videoMapSize
, kIOMapInhibitCache 
); 
2931     if (vars
->videoMapSize
) 
2932         ProgressUpdate(gIOHibernateGraphicsInfo
,  
2933                         (uint8_t *) vars
->videoMapping
, 0, kIOHibernateProgressCount
); 
2935     uint8_t * src 
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy(); 
2936     uint8_t * compressed 
= src 
+ page_size
; 
2937     uint8_t * scratch    
= compressed 
+ page_size
; 
2938     uint32_t  decoOffset
; 
2940     clock_get_uptime(&allTime
); 
2941     AbsoluteTime_to_scalar(&compTime
) = 0; 
2944     HIBLOG("IOHibernatePollerOpen(), ml_get_interrupts_enabled %d\n", ml_get_interrupts_enabled()); 
2945     err 
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledAfterSleepState
, 0); 
2946     clock_get_uptime(&startIOTime
); 
2947     endTime 
= startIOTime
; 
2948     SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2949     absolutetime_to_nanoseconds(endTime
, &nsec
); 
2950     HIBLOG("IOHibernatePollerOpen(%x) %qd ms\n", err
, nsec 
/ 1000000ULL); 
2952     IOPolledFileSeek(vars
->fileVars
, gIOHibernateCurrentHeader
->image1Size
); 
2954     // kick off the read ahead 
2955     vars
->fileVars
->io           
= false; 
2956     vars
->fileVars
->bufferHalf   
= 0; 
2957     vars
->fileVars
->bufferLimit  
= 0; 
2958     vars
->fileVars
->lastRead     
= 0; 
2959     vars
->fileVars
->readEnd      
= gIOHibernateCurrentHeader
->imageSize
; 
2960     vars
->fileVars
->bufferOffset 
= vars
->fileVars
->bufferLimit
; 
2961     vars
->fileVars
->cryptBytes   
= 0; 
2962     AbsoluteTime_to_scalar(&vars
->fileVars
->cryptTime
) = 0; 
2964     err 
= IOPolledFileRead(vars
->fileVars
, 0, 0, cryptvars
); 
2965     vars
->fileVars
->bufferOffset 
= vars
->fileVars
->bufferLimit
; 
2968     HIBLOG("hibernate_machine_init reading\n"); 
2970     uint32_t * header 
= (uint32_t *) src
; 
2973     while (kIOReturnSuccess 
== err
) 
2978         vm_offset_t  ppnum
, compressedSize
; 
2980         err 
= IOPolledFileRead(vars
->fileVars
, src
, 8, cryptvars
); 
2981         if (kIOReturnSuccess 
!= err
) 
2987 //      HIBPRINT("(%x, %x)\n", ppnum, count); 
2992         for (page 
= 0; page 
< count
; page
++) 
2994             err 
= IOPolledFileRead(vars
->fileVars
, (uint8_t *) &tag
, 4, cryptvars
); 
2995             if (kIOReturnSuccess 
!= err
) 
2998             compressedSize 
= kIOHibernateTagLength 
& tag
; 
2999             if (kIOHibernateTagSignature 
!= (tag 
& ~kIOHibernateTagLength
)) 
3001                 err 
= kIOReturnIPCError
; 
3005             if (!compressedSize
) bzero_phys(ptoa_64(ppnum
), page_size
); 
3008                 err 
= IOPolledFileRead(vars
->fileVars
, src
, (compressedSize 
+ 3) & ~3, cryptvars
); 
3009                 if (kIOReturnSuccess 
!= err
) break; 
3010                 if (compressedSize 
< page_size
) 
3012                     decoOffset 
= page_size
; 
3013                     clock_get_uptime(&startTime
); 
3014                     WKdm_decompress_new((WK_word
*) src
, (WK_word
*) compressed
, (WK_word
*) scratch
, page_size
); 
3015                     clock_get_uptime(&endTime
); 
3016                     ADD_ABSOLUTETIME(&compTime
, &endTime
); 
3017                     SUB_ABSOLUTETIME(&compTime
, &startTime
); 
3018                     compBytes 
+= page_size
; 
3020                 else decoOffset 
= 0; 
3022                 sum 
+= hibernate_sum_page((src 
+ decoOffset
), ppnum
); 
3023                 err 
= IOMemoryDescriptorReadToPhysical(vars
->srcBuffer
, decoOffset
, ptoa_64(ppnum
), page_size
); 
3026                     HIBLOG("IOMemoryDescriptorReadToPhysical [%ld] %x\n", (long)ppnum
, err
); 
3035             if (0 == (8191 & pagesDone
)) 
3037                 clock_get_uptime(&endTime
); 
3038                 SUB_ABSOLUTETIME(&endTime
, &allTime
); 
3039                 absolutetime_to_nanoseconds(endTime
, &nsec
); 
3040                 progressStamp 
= nsec 
/ 750000000ULL; 
3041                 if (progressStamp 
!= lastProgressStamp
) 
3043                     lastProgressStamp 
= progressStamp
; 
3044                     HIBPRINT("pages %d (%d%%)\n", pagesDone
,  
3045                             (100 * pagesDone
) / gIOHibernateCurrentHeader
->pageCount
); 
3050     if ((kIOReturnSuccess 
== err
) && (pagesDone 
== gIOHibernateCurrentHeader
->actualUncompressedPages
)) 
3051         err 
= kIOReturnLockedRead
; 
3053     if (kIOReturnSuccess 
!= err
) 
3054         panic("Hibernate restore error %x", err
); 
3056     gIOHibernateCurrentHeader
->actualImage2Sum 
= sum
; 
3057     gIOHibernateCompression 
= gIOHibernateCurrentHeader
->compression
; 
3059     if (vars
->fileVars
->io
) 
3060         (void) IOHibernatePollerIODone(vars
->fileVars
, false); 
3062     clock_get_uptime(&endIOTime
); 
3064     err 
= IOHibernatePollerClose(vars
->fileVars
, kIOPolledAfterSleepState
); 
3066     clock_get_uptime(&endTime
); 
3068     IOService::getPMRootDomain()->pmStatsRecordEvent(  
3069                         kIOPMStatsHibernateImageRead 
| kIOPMStatsEventStartFlag
, allTime
); 
3070     IOService::getPMRootDomain()->pmStatsRecordEvent(  
3071                         kIOPMStatsHibernateImageRead 
| kIOPMStatsEventStopFlag
, endTime
); 
3073     SUB_ABSOLUTETIME(&endTime
, &allTime
); 
3074     absolutetime_to_nanoseconds(endTime
, &nsec
); 
3076     SUB_ABSOLUTETIME(&endIOTime
, &startIOTime
); 
3077     absolutetime_to_nanoseconds(endIOTime
, &nsecIO
); 
3079     gIOHibernateStats
->kernelImageReadDuration 
= nsec 
/ 1000000ULL; 
3080     gIOHibernateStats
->imagePages              
= pagesDone
; 
3082     HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %d ms, disk(0x%x) %qd Mb/s, ",  
3083                 pagesDone
, sum
, gIOHibernateStats
->kernelImageReadDuration
, kDefaultIOSize
, 
3084                 nsecIO 
? ((((gIOHibernateCurrentHeader
->imageSize 
- gIOHibernateCurrentHeader
->image1Size
) * 1000000000ULL) / 1024 / 1024) / nsecIO
) : 0); 
3086     absolutetime_to_nanoseconds(compTime
, &nsec
); 
3087     HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",  
3090                 nsec 
? (((compBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
3092     absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
); 
3093     HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s\n",  
3094                 vars
->fileVars
->cryptBytes
,  
3096                 nsec 
? (((vars
->fileVars
->cryptBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
3098     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 2) | DBG_FUNC_NONE
, pagesRead
, pagesDone
, 0, 0, 0); 
3101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
3103 void IOHibernateSetWakeCapabilities(uint32_t capability
) 
3105     if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
3107         gIOHibernateStats
->wakeCapability 
= capability
; 
3111 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
3113 void IOHibernateSystemRestart(void) 
3115     static uint8_t    noteStore
[32] __attribute__((aligned(32))); 
3116     IORegistryEntry 
* regEntry
; 
3117     const OSSymbol 
*  sym
; 
3120     uintptr_t *       smcVars
; 
3125     data 
= OSDynamicCast(OSData
, IOService::getPMRootDomain()->getProperty(kIOHibernateSMCVariablesKey
)); 
3128     smcVars 
= (typeof(smcVars
)) data
->getBytesNoCopy(); 
3129     smcBytes 
= (typeof(smcBytes
)) smcVars
[1]; 
3131     if (len 
> sizeof(noteStore
)) len 
= sizeof(noteStore
); 
3132     noteProp 
= OSData::withCapacity(3 * sizeof(element
)); 
3133     if (!noteProp
) return; 
3135     noteProp
->appendBytes(&element
, sizeof(element
)); 
3136     element 
= crc32(0, smcBytes
, len
); 
3137     noteProp
->appendBytes(&element
, sizeof(element
)); 
3139     bcopy(smcBytes
, noteStore
, len
); 
3140     element 
= (addr64_t
) ¬eStore
[0]; 
3141     element 
= (element 
& page_mask
) | ptoa_64(pmap_find_phys(kernel_pmap
, element
)); 
3142     noteProp
->appendBytes(&element
, sizeof(element
)); 
3144     if (!gIOOptionsEntry
) 
3146         regEntry 
= IORegistryEntry::fromPath("/options", gIODTPlane
); 
3147         gIOOptionsEntry 
= OSDynamicCast(IODTNVRAM
, regEntry
); 
3148         if (regEntry 
&& !gIOOptionsEntry
) 
3149             regEntry
->release(); 
3152     sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootNoteKey
); 
3153     if (gIOOptionsEntry 
&& sym
) gIOOptionsEntry
->setProperty(sym
, noteProp
); 
3154     if (noteProp
)               noteProp
->release(); 
3155     if (sym
)                    sym
->release();