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 <libkern/WKdm.h> 
 169 #include "IOKitKernelInternal.h" 
 170 #include <pexpert/device_tree.h> 
 172 #include <machine/pal_routines.h> 
 173 #include <machine/pal_hibernate.h> 
 175 extern "C" addr64_t             
kvtophys(vm_offset_t va
); 
 176 extern "C" ppnum_t              
pmap_find_phys(pmap_t pmap
, addr64_t va
); 
 178 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 180 extern unsigned int             save_kdebug_enable
; 
 181 extern uint32_t                 gIOHibernateState
; 
 182 uint32_t                        gIOHibernateMode
; 
 183 static char                     gIOHibernateBootSignature
[256+1]; 
 184 static char                     gIOHibernateFilename
[MAXPATHLEN
+1]; 
 185 static uint32_t                 gIOHibernateFreeRatio 
= 0;              // free page target (percent) 
 186 uint32_t                        gIOHibernateFreeTime  
= 0*1000; // max time to spend freeing pages (ms) 
 188 static IODTNVRAM 
*              gIOOptionsEntry
; 
 189 static IORegistryEntry 
*        gIOChosenEntry
; 
 190 #if defined(__i386__) || defined(__x86_64__) 
 191 static const OSSymbol 
*         gIOCreateEFIDevicePathSymbol
; 
 192 static const OSSymbol 
*         gIOHibernateRTCVariablesKey
; 
 193 static const OSSymbol 
*         gIOHibernateBoot0082Key
; 
 194 static const OSSymbol 
*         gIOHibernateBootNextKey
; 
 195 static OSData 
*                 gIOHibernateBoot0082Data
; 
 196 static OSData 
*                 gIOHibernateBootNextData
; 
 197 static OSObject 
*               gIOHibernateBootNextSave
; 
 200 static IOLock 
*                           gFSLock
; 
 201 static uint32_t                           gFSState
; 
 202 static IOPolledFileIOVars                 gFileVars
; 
 203 static IOHibernateVars                    gIOHibernateVars
; 
 204 static struct kern_direct_file_io_ref_t 
* gIOHibernateFileRef
; 
 205 static hibernate_cryptvars_t              gIOHibernateCryptWakeContext
; 
 206 static hibernate_graphics_t               _hibernateGraphics
; 
 207 static hibernate_graphics_t 
*             gIOHibernateGraphicsInfo 
= &_hibernateGraphics
; 
 217 static IOReturn 
IOHibernateDone(IOHibernateVars 
* vars
); 
 219 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 221 enum { kXPRamAudioVolume 
= 8 }; 
 222 enum { kDefaultIOSize 
= 128 * 1024 }; 
 223 enum { kVideoMapSize  
= 32 * 1024 * 1024 }; 
 225 #ifndef kIOMediaPreferredBlockSizeKey 
 226 #define kIOMediaPreferredBlockSizeKey   "Preferred Block Size" 
 229 #ifndef kIOBootPathKey   
 230 #define kIOBootPathKey                  "bootpath" 
 232 #ifndef kIOSelectedBootDeviceKey         
 233 #define kIOSelectedBootDeviceKey        "boot-device" 
 237 enum { kIOHibernateMinPollersNeeded 
= 2 }; 
 239 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 241 // copy from phys addr to MD 
 244 IOMemoryDescriptorWriteFromPhysical(IOMemoryDescriptor 
* md
, 
 245                                     IOByteCount offset
, addr64_t bytes
, IOByteCount length
) 
 247     addr64_t srcAddr 
= bytes
; 
 248     IOByteCount remaining
; 
 250     remaining 
= length 
= min(length
, md
->getLength() - offset
); 
 251     while (remaining
) { // (process another target segment?) 
 255         dstAddr64 
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
); 
 259         // Clip segment length to remaining 
 260         if (dstLen 
> remaining
) 
 264         bcopy_phys(srcAddr
, dstAddr64
, dstLen
); 
 266         copypv(srcAddr
, dstAddr64
, dstLen
, 
 267                             cppvPsnk 
| cppvFsnk 
| cppvNoRefSrc 
| cppvNoModSnk 
| cppvKmap
); 
 276     return remaining 
? kIOReturnUnderrun 
: kIOReturnSuccess
; 
 279 // copy from MD to phys addr 
 282 IOMemoryDescriptorReadToPhysical(IOMemoryDescriptor 
* md
, 
 283                                  IOByteCount offset
, addr64_t bytes
, IOByteCount length
) 
 285     addr64_t dstAddr 
= bytes
; 
 286     IOByteCount remaining
; 
 288     remaining 
= length 
= min(length
, md
->getLength() - offset
); 
 289     while (remaining
) { // (process another target segment?) 
 293         srcAddr64 
= md
->getPhysicalSegment(offset
, &dstLen
, kIOMemoryMapperNone
); 
 297         // Clip segment length to remaining 
 298         if (dstLen 
> remaining
) 
 302         bcopy_phys(srcAddr64
, dstAddr
, dstLen
); 
 304         copypv(srcAddr
, dstAddr64
, dstLen
, 
 305                             cppvPsnk 
| cppvFsnk 
| cppvNoRefSrc 
| cppvNoModSnk 
| cppvKmap
); 
 314     return remaining 
? kIOReturnUnderrun 
: kIOReturnSuccess
; 
 317 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 320 hibernate_set_page_state(hibernate_page_list_t 
* page_list
, hibernate_page_list_t 
* page_list_wired
, 
 321                                 vm_offset_t ppnum
, vm_offset_t count
, uint32_t kind
) 
 326       case kIOHibernatePageStateUnwiredSave
: 
 328         for (; ppnum 
< count
; ppnum
++) 
 330             hibernate_page_bitset(page_list
,       FALSE
, ppnum
); 
 331             hibernate_page_bitset(page_list_wired
, TRUE
,  ppnum
); 
 334       case kIOHibernatePageStateWiredSave
: 
 336         for (; ppnum 
< count
; ppnum
++) 
 338             hibernate_page_bitset(page_list
,       FALSE
, ppnum
); 
 339             hibernate_page_bitset(page_list_wired
, FALSE
, ppnum
); 
 342       case kIOHibernatePageStateFree
: 
 344         for (; ppnum 
< count
; ppnum
++) 
 346             hibernate_page_bitset(page_list
,       TRUE
, ppnum
); 
 347             hibernate_page_bitset(page_list_wired
, TRUE
, ppnum
); 
 351         panic("hibernate_set_page_state"); 
 356 hibernate_page_list_iterate(hibernate_page_list_t 
* list
, vm_offset_t 
* pPage
) 
 358     uint32_t             page 
= *pPage
; 
 360     hibernate_bitmap_t 
* bitmap
; 
 362     while ((bitmap 
= hibernate_page_bitmap_pin(list
, &page
))) 
 364         count 
= hibernate_page_bitmap_count(bitmap
, TRUE
, page
); 
 368         if (page 
<= bitmap
->last_page
) 
 374         count 
= hibernate_page_bitmap_count(bitmap
, FALSE
, page
); 
 381 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 384 IOHibernatePollerProbe(IOPolledFileIOVars 
* vars
, IOService 
* target
) 
 386     IOReturn            err 
= kIOReturnError
; 
 388     IOPolledInterface 
* poller
; 
 390     for (idx 
= vars
->pollers
->getCount() - 1; idx 
>= 0; idx
--) 
 392         poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
); 
 393         err 
= poller
->probe(target
); 
 396             HIBLOG("IOPolledInterface::probe[%d] 0x%x\n", idx
, err
); 
 405 IOHibernatePollerOpen(IOPolledFileIOVars 
* vars
, uint32_t state
, IOMemoryDescriptor 
* md
) 
 407     IOReturn            err 
= kIOReturnError
; 
 409     IOPolledInterface 
* poller
; 
 411     for (idx 
= vars
->pollers
->getCount() - 1; idx 
>= 0; idx
--) 
 413         poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
); 
 414         err 
= poller
->open(state
, md
); 
 417             HIBLOG("IOPolledInterface::open[%d] 0x%x\n", idx
, err
); 
 426 IOHibernatePollerClose(IOPolledFileIOVars 
* vars
, uint32_t state
) 
 428     IOReturn            err 
= kIOReturnError
; 
 430     IOPolledInterface 
* poller
; 
 433          (poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
)); 
 436         err 
= poller
->close(state
); 
 438             HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx
, err
); 
 445 IOHibernatePollerIOComplete(void *   target
, 
 448                             UInt64   actualByteCount
) 
 450     IOPolledFileIOVars 
* vars 
= (IOPolledFileIOVars 
*) parameter
; 
 452     vars
->ioStatus 
= status
; 
 456 IOHibernatePollerIO(IOPolledFileIOVars 
* vars
,  
 457                     uint32_t operation
, uint32_t bufferOffset
,  
 458                     uint64_t deviceOffset
, uint64_t length
) 
 461     IOReturn            err 
= kIOReturnError
; 
 462     IOPolledInterface 
* poller
; 
 463     IOPolledCompletion  completion
; 
 465     completion
.target    
= 0; 
 466     completion
.action    
= &IOHibernatePollerIOComplete
; 
 467     completion
.parameter 
= vars
; 
 471     poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(0); 
 472     err 
= poller
->startIO(operation
, bufferOffset
, deviceOffset 
+ vars
->block0
, length
, completion
); 
 474         HIBLOG("IOPolledInterface::startIO[%d] 0x%x\n", 0, err
); 
 480 IOHibernatePollerIODone(IOPolledFileIOVars 
* vars
, bool abortable
) 
 482     IOReturn            err 
= kIOReturnSuccess
; 
 484     IOPolledInterface 
* poller
; 
 486     while (-1 == vars
->ioStatus
) 
 489             (poller 
= (IOPolledInterface 
*) vars
->pollers
->getObject(idx
)); 
 493             newErr 
= poller
->checkForWork(); 
 494             if ((newErr 
== kIOReturnAborted
) && !abortable
) 
 495                 newErr 
= kIOReturnSuccess
; 
 496             if (kIOReturnSuccess 
== err
) 
 501     if ((kIOReturnSuccess 
== err
) && abortable 
&& hibernate_should_abort()) 
 503         err 
= kIOReturnAborted
; 
 504         HIBLOG("IOPolledInterface::checkForWork sw abort\n"); 
 509         HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx
, err
); 
 513         err 
= vars
->ioStatus
; 
 514         if (kIOReturnSuccess 
!= err
) 
 515             HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err
); 
 522 IOPolledInterface::checkAllForWork(void) 
 524     IOReturn            err 
= kIOReturnNotReady
; 
 526     IOPolledInterface 
* poller
; 
 528     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
 530     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers
) 
 534             (poller 
= (IOPolledInterface 
*) vars
->fileVars
->pollers
->getObject(idx
)); 
 537         err 
= poller
->checkForWork(); 
 539             HIBLOG("IOPolledInterface::checkAllForWork[%d] 0x%x\n", idx
, err
); 
 545 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 547 struct _OpenFileContext
 
 554 file_extent_callback(void * ref
, uint64_t start
, uint64_t length
) 
 556     _OpenFileContext 
* ctx 
= (_OpenFileContext 
*) ref
; 
 557     IOPolledFileExtent extent
; 
 559     extent
.start  
= start
; 
 560     extent
.length 
= length
; 
 562     ctx
->extents
->appendBytes(&extent
, sizeof(extent
)); 
 567 IOCopyMediaForDev(dev_t device
) 
 569     OSDictionary 
* matching
; 
 572     IOService 
*    result 
= 0; 
 574     matching 
= IOService::serviceMatching("IOMedia"); 
 579         num 
= OSNumber::withNumber(major(device
), 32); 
 582         matching
->setObject(kIOBSDMajorKey
, num
); 
 584         num 
= OSNumber::withNumber(minor(device
), 32); 
 587         matching
->setObject(kIOBSDMinorKey
, num
); 
 591         iter 
= IOService::getMatchingServices(matching
); 
 594             result 
= (IOService 
*) iter
->getNextObject(); 
 606 IOPolledFileOpen( const char * filename
, IOBufferMemoryDescriptor 
* ioBuffer
, 
 607                             IOPolledFileIOVars 
** fileVars
, OSData 
** fileExtents
, 
 608                             OSData 
** imagePath
, uint8_t * volumeCryptKey
) 
 610     IOReturn                    err 
= kIOReturnSuccess
; 
 611     IOPolledFileIOVars 
*        vars
; 
 612     _OpenFileContext            ctx
; 
 613     OSData 
*                    extentsData
; 
 615     IOService 
*                 part 
= 0; 
 616     OSString 
*                  keyUUID 
= 0; 
 617     OSString 
*                  keyStoreUUID 
= 0; 
 619     dev_t                       hibernate_image_dev
; 
 621     AbsoluteTime                startTime
, endTime
; 
 624     vars 
= IONew(IOPolledFileIOVars
, 1); 
 625     if (!vars
) return (kIOReturnNoMemory
); 
 626     bzero(vars
, sizeof(*vars
)); 
 630         HIBLOG("sizeof(IOHibernateImageHeader) == %ld\n", sizeof(IOHibernateImageHeader
)); 
 631         if (sizeof(IOHibernateImageHeader
) != 512) 
 635         vars
->buffer       
= (uint8_t *) ioBuffer
->getBytesNoCopy(); 
 636         vars
->bufferHalf   
= 0; 
 637         vars
->bufferOffset 
= 0; 
 638         vars
->bufferSize   
= ioBuffer
->getLength() >> 1; 
 640         extentsData 
= OSData::withCapacity(32); 
 641         ctx
.extents 
= extentsData
; 
 643         clock_get_uptime(&startTime
); 
 644         vars
->fileRef 
= kern_open_file_for_direct_io(filename
,  
 645                                                     &file_extent_callback
, &ctx
,  
 647                                                     &hibernate_image_dev
, 
 651                                                     0, (caddr_t
) gIOHibernateCurrentHeader
,  
 652                                                     sizeof(IOHibernateImageHeader
)); 
 654         uint32_t msDelay 
= (131071 & random()); 
 655         HIBLOG("sleep %d\n", msDelay
); 
 658         clock_get_uptime(&endTime
); 
 659         SUB_ABSOLUTETIME(&endTime
, &startTime
); 
 660         absolutetime_to_nanoseconds(endTime
, &nsec
); 
 662         if (!vars
->fileRef
) err 
= kIOReturnNoSpace
; 
 665         if (kFSOpening 
!= gFSState
) err 
= kIOReturnTimeout
; 
 666         IOLockUnlock(gFSLock
); 
 668         HIBLOG("kern_open_file_for_direct_io(%d) took %qd ms\n", err
, nsec 
/ 1000000ULL); 
 669         if (kIOReturnSuccess 
!= err
) break; 
 671         if (kIOHibernateModeSSDInvert 
& gIOHibernateMode
) 
 672             vars
->flags 
^= kIOHibernateOptionSSD
; 
 674         HIBLOG("Opened file %s, size %qd, partition base 0x%qx, maxio %qx ssd %d\n", filename
, ctx
.size
,  
 675                     vars
->block0
, maxiobytes
, kIOHibernateOptionSSD 
& vars
->flags
); 
 676         if (ctx
.size 
< 1*1024*1024)             // check against image size estimate! 
 678             err 
= kIOReturnNoSpace
; 
 682         if (maxiobytes 
< vars
->bufferSize
) 
 683             vars
->bufferSize 
= maxiobytes
; 
 685         vars
->extentMap 
= (IOPolledFileExtent 
*) extentsData
->getBytesNoCopy(); 
 687         part 
= IOCopyMediaForDev(block_dev
); 
 691         err 
= part
->callPlatformFunction(PLATFORM_FUNCTION_GET_MEDIA_ENCRYPTION_KEY_UUID
, false,  
 692                                           (void *) &keyUUID
, (void *) &keyStoreUUID
, NULL
, NULL
); 
 693         if ((kIOReturnSuccess 
== err
) && keyUUID 
&& keyStoreUUID
) 
 695 //            IOLog("got volume key %s\n", keyStoreUUID->getCStringNoCopy()); 
 696             uuid_t                  volumeKeyUUID
; 
 697             aks_volume_key_t        vek
; 
 698             static IOService 
*      sKeyStore
; 
 699             static const OSSymbol 
* sAKSGetKey
; 
 702                 sAKSGetKey 
= OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY
); 
 704                 sKeyStore 
= (IOService 
*) IORegistryEntry::fromPath(AKS_SERVICE_PATH
, gIOServicePlane
); 
 706                 err 
= uuid_parse(keyStoreUUID
->getCStringNoCopy(), volumeKeyUUID
); 
 708                 err 
= kIOReturnNoResources
; 
 709             if (kIOReturnSuccess 
== err
)     
 710                 err 
= sKeyStore
->callPlatformFunction(sAKSGetKey
, true, volumeKeyUUID
, &vek
, NULL
, NULL
); 
 711             if (kIOReturnSuccess 
!= err
)     
 712                 IOLog("volume key err 0x%x\n", err
); 
 715                 size_t bytes 
= (kIOHibernateAESKeySize 
/ 8); 
 716                 if (vek
.key
.keybytecount 
< bytes
) 
 717                      bytes 
= vek
.key
.keybytecount
; 
 718                 bcopy(&vek
.key
.keybytes
[0], volumeCryptKey
, bytes
); 
 720             bzero(&vek
, sizeof(vek
)); 
 724         part 
= IOCopyMediaForDev(hibernate_image_dev
); 
 728         IORegistryEntry 
* next
; 
 729         IORegistryEntry 
* child
; 
 732         vars
->pollers 
= OSArray::withCapacity(4); 
 736         vars
->blockSize 
= 512; 
 740             IOPolledInterface 
* poller
; 
 743             obj 
= next
->getProperty(kIOPolledInterfaceSupportKey
); 
 744             if (kOSBooleanFalse 
== obj
) 
 746                 vars
->pollers
->flushCollection(); 
 749             else if ((poller 
= OSDynamicCast(IOPolledInterface
, obj
))) 
 750                 vars
->pollers
->setObject(poller
); 
 751             if ((num 
= OSDynamicCast(OSNumber
, next
->getProperty(kIOMediaPreferredBlockSizeKey
)))) 
 752                 vars
->blockSize 
= num
->unsigned32BitValue(); 
 755         while ((next 
= child
->getParentEntry(gIOServicePlane
))  
 756                 && child
->isParent(next
, gIOServicePlane
, true)); 
 758         HIBLOG("hibernate image major %d, minor %d, blocksize %ld, pollers %d\n", 
 759                     major(hibernate_image_dev
), minor(hibernate_image_dev
), (long)vars
->blockSize
, vars
->pollers
->getCount()); 
 760         if (vars
->pollers
->getCount() < kIOHibernateMinPollersNeeded
) 
 763         err 
= IOHibernatePollerProbe(vars
, (IOService 
*) part
); 
 764         if (kIOReturnSuccess 
!= err
) 
 767         err 
= IOHibernatePollerOpen(vars
, kIOPolledPreflightState
, ioBuffer
); 
 768         if (kIOReturnSuccess 
!= err
) 
 772         *fileExtents 
= extentsData
; 
 776         if ((extentsData
->getLength() >= sizeof(IOPolledFileExtent
))) 
 778             char str2
[24 + sizeof(uuid_string_t
) + 2]; 
 780 #if defined(__i386__) || defined(__x86_64__) 
 781             if (!gIOCreateEFIDevicePathSymbol
) 
 782                 gIOCreateEFIDevicePathSymbol 
= OSSymbol::withCString("CreateEFIDevicePath"); 
 785                 snprintf(str2
, sizeof(str2
), "%qx:%s",  
 786                                 vars
->extentMap
[0].start
, keyUUID
->getCStringNoCopy()); 
 788                 snprintf(str2
, sizeof(str2
), "%qx", vars
->extentMap
[0].start
); 
 790             err 
= IOService::getPlatform()->callPlatformFunction( 
 791                                                 gIOCreateEFIDevicePathSymbol
, false, 
 792                                                 (void *) part
, (void *) str2
, 
 793                                                 (void *) (uintptr_t) true, (void *) &data
); 
 796             int len 
= sizeof(str1
); 
 798             if (!part
->getPath(str1
, &len
, gIODTPlane
)) 
 799                 err 
= kIOReturnNotFound
; 
 802                 snprintf(str2
, sizeof(str2
), ",%qx", vars
->extentMap
[0].start
); 
 803                 // (strip the plane name) 
 804                 char * tail 
= strchr(str1
, ':'); 
 807                 data 
= OSData::withBytes(tail 
+ 1, strlen(tail 
+ 1)); 
 808                 data
->appendBytes(str2
, strlen(str2
)); 
 811         if (kIOReturnSuccess 
== err
) 
 814             HIBLOG("error 0x%x getting path\n", err
); 
 819     if (kIOReturnSuccess 
!= err
) 
 821         HIBLOG("error 0x%x opening hibernation file\n", err
); 
 824             kern_close_file_for_direct_io(vars
->fileRef
, 0, 0, 0, 0, 0); 
 825             vars
->fileRef 
= NULL
; 
 836 IOPolledFileClose( IOPolledFileIOVars 
* vars 
) 
 840         IOHibernatePollerClose(vars
, kIOPolledPostflightState
); 
 841         vars
->pollers
->release(); 
 844     bzero(vars
, sizeof(IOPolledFileIOVars
)); 
 846     return (kIOReturnSuccess
); 
 850 IOPolledFileSeek(IOPolledFileIOVars 
* vars
, uint64_t position
) 
 852     IOPolledFileExtent 
* extentMap
; 
 854     extentMap 
= vars
->extentMap
; 
 856     vars
->position 
= position
; 
 858     while (position 
>= extentMap
->length
) 
 860         position 
-= extentMap
->length
; 
 864     vars
->currentExtent   
= extentMap
; 
 865     vars
->extentRemaining 
= extentMap
->length 
- position
; 
 866     vars
->extentPosition  
= vars
->position 
- position
; 
 868     if (vars
->bufferSize 
<= vars
->extentRemaining
) 
 869         vars
->bufferLimit 
= vars
->bufferSize
; 
 871         vars
->bufferLimit 
= vars
->extentRemaining
; 
 873     return (kIOReturnSuccess
); 
 877 IOPolledFileWrite(IOPolledFileIOVars 
* vars
, 
 878                     const uint8_t * bytes
, IOByteCount size
, 
 879                     hibernate_cryptvars_t 
* cryptvars
) 
 881     IOReturn    err 
= kIOReturnSuccess
; 
 889             // seek to end of block & flush 
 890             size 
= vars
->position 
& (vars
->blockSize 
- 1); 
 892                 size 
= vars
->blockSize 
- size
; 
 894             // use some garbage for the fill 
 895             bytes 
= vars
->buffer 
+ vars
->bufferOffset
; 
 898         copy 
= vars
->bufferLimit 
- vars
->bufferOffset
; 
 906             bcopy(bytes
, vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, copy
); 
 910             bzero(vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, copy
); 
 913         vars
->bufferOffset 
+= copy
; 
 914         vars
->position 
+= copy
; 
 916         if (flush 
&& vars
->bufferOffset
) 
 918             uint64_t offset 
= (vars
->position 
- vars
->bufferOffset 
 
 919                                 - vars
->extentPosition 
+ vars
->currentExtent
->start
); 
 920             uint32_t length 
= (vars
->bufferOffset
); 
 923             if (cryptvars 
&& vars
->encryptStart
 
 924                 && (vars
->position 
> vars
->encryptStart
) 
 925                 && ((vars
->position 
- length
) < vars
->encryptEnd
)) 
 927                 AbsoluteTime startTime
, endTime
; 
 929                 uint64_t encryptLen
, encryptStart
; 
 930                 encryptLen 
= vars
->position 
- vars
->encryptStart
; 
 931                 if (encryptLen 
> length
) 
 933                 encryptStart 
= length 
- encryptLen
; 
 934                 if (vars
->position 
> vars
->encryptEnd
) 
 935                     encryptLen 
-= (vars
->position 
- vars
->encryptEnd
); 
 937                 clock_get_uptime(&startTime
); 
 939                 // encrypt the buffer 
 940                 aes_encrypt_cbc(vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart
, 
 941                                 &cryptvars
->aes_iv
[0], 
 942                                 encryptLen 
/ AES_BLOCK_SIZE
, 
 943                                 vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart
, 
 944                                 &cryptvars
->ctx
.encrypt
); 
 946                 clock_get_uptime(&endTime
); 
 947                 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
); 
 948                 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
); 
 949                 vars
->cryptBytes 
+= encryptLen
; 
 951                 // save initial vector for following encrypts 
 952                 bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ encryptStart 
+ encryptLen 
- AES_BLOCK_SIZE
, 
 953                         &cryptvars
->aes_iv
[0], 
 960                 err 
= IOHibernatePollerIODone(vars
, true); 
 961                 if (kIOReturnSuccess 
!= err
) 
 965 if (vars
->position 
& (vars
->blockSize 
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
); 
 966 //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length); 
 968             err 
= IOHibernatePollerIO(vars
, kIOPolledWrite
, vars
->bufferHalf
, offset
, length
); 
 969             if (kIOReturnSuccess 
!= err
) 
 973             vars
->extentRemaining 
-= vars
->bufferOffset
; 
 974             if (!vars
->extentRemaining
) 
 976                 vars
->currentExtent
++; 
 977                 vars
->extentRemaining 
= vars
->currentExtent
->length
; 
 978                 vars
->extentPosition  
= vars
->position
; 
 979                 if (!vars
->extentRemaining
) 
 981                     err 
= kIOReturnOverrun
; 
 986             vars
->bufferHalf 
= vars
->bufferHalf 
? 0 : vars
->bufferSize
; 
 987             vars
->bufferOffset 
= 0; 
 988             if (vars
->bufferSize 
<= vars
->extentRemaining
) 
 989                 vars
->bufferLimit 
= vars
->bufferSize
; 
 991                 vars
->bufferLimit 
= vars
->extentRemaining
; 
1002 IOPolledFileRead(IOPolledFileIOVars 
* vars
, 
1003                     uint8_t * bytes
, IOByteCount size
, 
1004                     hibernate_cryptvars_t 
* cryptvars
) 
1006     IOReturn    err 
= kIOReturnSuccess
; 
1009 //    bytesWritten += size; 
1013         copy 
= vars
->bufferLimit 
- vars
->bufferOffset
; 
1019             bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ vars
->bufferOffset
, bytes
, copy
); 
1023         vars
->bufferOffset 
+= copy
; 
1024 //      vars->position += copy; 
1026         if ((vars
->bufferOffset 
== vars
->bufferLimit
) && (vars
->position 
< vars
->readEnd
)) 
1030                 err 
= IOHibernatePollerIODone(vars
, false); 
1031                 if (kIOReturnSuccess 
!= err
) 
1037 if (vars
->position 
& (vars
->blockSize 
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
); 
1039             vars
->position        
+= vars
->lastRead
; 
1040             vars
->extentRemaining 
-= vars
->lastRead
; 
1041             vars
->bufferLimit      
= vars
->lastRead
; 
1043             if (!vars
->extentRemaining
) 
1045                 vars
->currentExtent
++; 
1046                 vars
->extentRemaining 
= vars
->currentExtent
->length
; 
1047                 vars
->extentPosition  
= vars
->position
; 
1048                 if (!vars
->extentRemaining
) 
1050                     err 
= kIOReturnOverrun
; 
1056             uint64_t lastReadLength 
= vars
->lastRead
; 
1057             uint64_t offset 
= (vars
->position 
 
1058                                 - vars
->extentPosition 
+ vars
->currentExtent
->start
); 
1059             if (vars
->extentRemaining 
<= vars
->bufferSize
) 
1060                 length 
= vars
->extentRemaining
; 
1062                 length 
= vars
->bufferSize
; 
1063             if ((length 
+ vars
->position
) > vars
->readEnd
) 
1064                 length 
= vars
->readEnd 
- vars
->position
; 
1066             vars
->lastRead 
= length
; 
1069 //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length); 
1070                 err 
= IOHibernatePollerIO(vars
, kIOPolledRead
, vars
->bufferHalf
, offset
, length
); 
1071                 if (kIOReturnSuccess 
!= err
) 
1076             vars
->bufferHalf 
= vars
->bufferHalf 
? 0 : vars
->bufferSize
; 
1077             vars
->bufferOffset 
= 0; 
1082                 uint8_t thisVector
[AES_BLOCK_SIZE
]; 
1083                 AbsoluteTime startTime
, endTime
; 
1085                 // save initial vector for following decrypts 
1086                 bcopy(&cryptvars
->aes_iv
[0], &thisVector
[0], AES_BLOCK_SIZE
); 
1087                 bcopy(vars
->buffer 
+ vars
->bufferHalf 
+ lastReadLength 
- AES_BLOCK_SIZE
,  
1088                         &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
); 
1090                 // decrypt the buffer 
1091                 clock_get_uptime(&startTime
); 
1093                 aes_decrypt_cbc(vars
->buffer 
+ vars
->bufferHalf
, 
1095                                 lastReadLength 
/ AES_BLOCK_SIZE
, 
1096                                 vars
->buffer 
+ vars
->bufferHalf
, 
1097                                 &cryptvars
->ctx
.decrypt
); 
1099                 clock_get_uptime(&endTime
); 
1100                 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
); 
1101                 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
); 
1102                 vars
->cryptBytes 
+= lastReadLength
; 
1112 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1115 IOHibernateSystemSleep(void) 
1122     IOHibernateVars 
* vars
; 
1124     gIOHibernateState 
= kIOHibernateStateInactive
; 
1126     if (!gIOChosenEntry
) 
1127         gIOChosenEntry 
= IORegistryEntry::fromPath("/chosen", gIODTPlane
); 
1129     gIOHibernateDebugFlags 
= 0; 
1130     if (kIOLogHibernate 
& gIOKitDebug
) 
1131         gIOHibernateDebugFlags 
|= kIOHibernateDebugRestoreLogs
; 
1133     if (IOService::getPMRootDomain()->getHibernateSettings( 
1134         &gIOHibernateMode
, &gIOHibernateFreeRatio
, &gIOHibernateFreeTime
)) 
1136         if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
1137             // default to discard clean for safe sleep 
1138             gIOHibernateMode 
^= (kIOHibernateModeDiscardCleanInactive 
 
1139                                 | kIOHibernateModeDiscardCleanActive
); 
1142     if ((obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey
))) 
1144         if ((str 
= OSDynamicCast(OSString
, obj
))) 
1145             strlcpy(gIOHibernateFilename
, str
->getCStringNoCopy(), 
1146                             sizeof(gIOHibernateFilename
)); 
1150     if (!gIOHibernateMode 
|| !gIOHibernateFilename
[0]) 
1151         return (kIOReturnUnsupported
); 
1153     HIBLOG("hibernate image path: %s\n", gIOHibernateFilename
); 
1155     vars 
= IONew(IOHibernateVars
, 1); 
1156     if (!vars
) return (kIOReturnNoMemory
); 
1157     bzero(vars
, sizeof(*vars
)); 
1159     IOLockLock(gFSLock
); 
1160     if (kFSIdle 
!= gFSState
) 
1162         HIBLOG("hibernate file busy\n"); 
1163         IOLockUnlock(gFSLock
); 
1164         IODelete(vars
, IOHibernateVars
, 1); 
1165         return (kIOReturnBusy
); 
1167     gFSState 
= kFSOpening
; 
1168     IOLockUnlock(gFSLock
); 
1172         vars
->srcBuffer 
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
, 
1173                                     4 * page_size
, page_size
); 
1174         vars
->ioBuffer  
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,  
1175                                     2 * kDefaultIOSize
, page_size
); 
1177         vars
->handoffBuffer 
= IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn
,  
1178                                     ptoa_64(gIOHibernateHandoffPageCount
), page_size
); 
1180         if (!vars
->srcBuffer 
|| !vars
->ioBuffer 
|| !vars
->handoffBuffer
) 
1182             err 
= kIOReturnNoMemory
; 
1186         // open & invalidate the image file 
1187         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderInvalidSignature
; 
1188         err 
= IOPolledFileOpen(gIOHibernateFilename
, vars
->ioBuffer
, 
1189                                 &vars
->fileVars
, &vars
->fileExtents
, &data
,  
1190                                 &vars
->volumeCryptKey
[0]); 
1191         if (KERN_SUCCESS 
!= err
) 
1193             HIBLOG("IOPolledFileOpen(%x)\n", err
); 
1197         bzero(gIOHibernateCurrentHeader
, sizeof(IOHibernateImageHeader
)); 
1198         gIOHibernateCurrentHeader
->debugFlags 
= gIOHibernateDebugFlags
; 
1199         dsSSD 
= ((0 != (kIOHibernateOptionSSD 
& vars
->fileVars
->flags
)) 
1200                 && (kOSBooleanTrue 
== IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey
))); 
1203             gIOHibernateCurrentHeader
->options 
|=  
1204                                                 kIOHibernateOptionSSD
 
1205                                               | kIOHibernateOptionColor
; 
1207 #if defined(__i386__) || defined(__x86_64__) 
1208             if (!uuid_is_null(vars
->volumeCryptKey
) && 
1209                   (kOSBooleanTrue 
!= IOService::getPMRootDomain()->getProperty(kIOPMDestroyFVKeyOnStandbyKey
))) 
1211                 uintptr_t smcVars
[2]; 
1212                 smcVars
[0] = sizeof(vars
->volumeCryptKey
); 
1213                 smcVars
[1] = (uintptr_t)(void *) &gIOHibernateVars
.volumeCryptKey
[0]; 
1215                 IOService::getPMRootDomain()->setProperty(kIOHibernateSMCVariablesKey
, smcVars
, sizeof(smcVars
)); 
1216                 bzero(smcVars
, sizeof(smcVars
)); 
1222             gIOHibernateCurrentHeader
->options 
|= kIOHibernateOptionProgress
; 
1225         boolean_t encryptedswap
; 
1226         AbsoluteTime startTime
, endTime
; 
1229         clock_get_uptime(&startTime
); 
1230         err 
= hibernate_setup(gIOHibernateCurrentHeader
,  
1231                                 gIOHibernateFreeRatio
, gIOHibernateFreeTime
, 
1233                                 &vars
->page_list
, &vars
->page_list_wired
, &vars
->page_list_pal
, &encryptedswap
); 
1234         clock_get_uptime(&endTime
); 
1235         SUB_ABSOLUTETIME(&endTime
, &startTime
); 
1236         absolutetime_to_nanoseconds(endTime
, &nsec
); 
1237         HIBLOG("hibernate_setup(%d) took %qd ms\n", err
, nsec 
/ 1000000ULL); 
1239         if (KERN_SUCCESS 
!= err
) 
1242         if (encryptedswap 
|| !uuid_is_null(vars
->volumeCryptKey
)) 
1243             gIOHibernateMode 
^= kIOHibernateModeEncrypt
;  
1245         if (kIOHibernateOptionProgress 
& gIOHibernateCurrentHeader
->options
) 
1247             vars
->videoAllocSize 
= kVideoMapSize
; 
1248             if (KERN_SUCCESS 
!= kmem_alloc_pageable(kernel_map
, &vars
->videoMapping
, vars
->videoAllocSize
)) 
1249                 vars
->videoMapping 
= 0; 
1252         // generate crypt keys 
1253         for (uint32_t i 
= 0; i 
< sizeof(vars
->wiredCryptKey
); i
++) 
1254             vars
->wiredCryptKey
[i
] = random(); 
1255         for (uint32_t i 
= 0; i 
< sizeof(vars
->cryptKey
); i
++) 
1256             vars
->cryptKey
[i
] = random(); 
1260         IORegistryEntry 
* regEntry
; 
1261         if (!gIOOptionsEntry
) 
1263             regEntry 
= IORegistryEntry::fromPath("/options", gIODTPlane
); 
1264             gIOOptionsEntry 
= OSDynamicCast(IODTNVRAM
, regEntry
); 
1265             if (regEntry 
&& !gIOOptionsEntry
) 
1266                 regEntry
->release(); 
1269         if (gIOOptionsEntry
) 
1271             const OSSymbol 
*  sym
; 
1273             sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey
); 
1276                 gIOOptionsEntry
->setProperty(sym
, data
); 
1281 #if defined(__i386__) || defined(__x86_64__) 
1282             struct AppleRTCHibernateVars
 
1284                 uint8_t     signature
[4]; 
1286                 uint8_t     booterSignature
[20]; 
1287                 uint8_t     wiredCryptKey
[16]; 
1289             AppleRTCHibernateVars rtcVars
; 
1291             rtcVars
.signature
[0] = 'A'; 
1292             rtcVars
.signature
[1] = 'A'; 
1293             rtcVars
.signature
[2] = 'P'; 
1294             rtcVars
.signature
[3] = 'L'; 
1295             rtcVars
.revision     
= 1; 
1296             bcopy(&vars
->wiredCryptKey
[0], &rtcVars
.wiredCryptKey
[0], sizeof(rtcVars
.wiredCryptKey
)); 
1297             if (gIOHibernateBootSignature
[0]) 
1301                 for (uint32_t i 
= 0; 
1302                     (c 
= gIOHibernateBootSignature
[i
]) && (i 
< (sizeof(rtcVars
.booterSignature
) << 1)); 
1313                     value 
= (value 
<< 4) | c
; 
1315                         rtcVars
.booterSignature
[i 
>> 1] = value
; 
1318             data 
= OSData::withBytes(&rtcVars
, sizeof(rtcVars
)); 
1321                 if (!gIOHibernateRTCVariablesKey
) 
1322                     gIOHibernateRTCVariablesKey 
= OSSymbol::withCStringNoCopy(kIOHibernateRTCVariablesKey
); 
1323                 if (gIOHibernateRTCVariablesKey
) 
1324                     IOService::getPMRootDomain()->setProperty(gIOHibernateRTCVariablesKey
, data
); 
1326                 if( gIOOptionsEntry 
) 
1328                     if( gIOHibernateMode 
& kIOHibernateModeSwitch 
) 
1330                         const OSSymbol 
*sym
; 
1331                         sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootSwitchVarsKey
); 
1334                             gIOOptionsEntry
->setProperty(sym
, data
); /* intentional insecure backup of rtc boot vars */ 
1344                 data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOHibernateMachineSignatureKey
)); 
1346                     gIOHibernateCurrentHeader
->machineSignature 
= *((UInt32 
*)data
->getBytesNoCopy()); 
1350                     if (!gIOHibernateBoot0082Data
) 
1352                         data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty("boot-device-path")); 
1355                             // AppleNVRAM_EFI_LOAD_OPTION 
1357                                 uint32_t Attributes
; 
1358                                 uint16_t FilePathLength
; 
1361                             loadOptionHeader
.Attributes     
= 1; 
1362                             loadOptionHeader
.FilePathLength 
= data
->getLength(); 
1363                             loadOptionHeader
.Desc           
= 0; 
1364                             gIOHibernateBoot0082Data 
= OSData::withCapacity(sizeof(loadOptionHeader
) + loadOptionHeader
.FilePathLength
); 
1365                             if (gIOHibernateBoot0082Data
) 
1367                                 gIOHibernateBoot0082Data
->appendBytes(&loadOptionHeader
, sizeof(loadOptionHeader
)); 
1368                                 gIOHibernateBoot0082Data
->appendBytes(data
); 
1372                     if (!gIOHibernateBoot0082Key
) 
1373                         gIOHibernateBoot0082Key 
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:Boot0082"); 
1374                     if (!gIOHibernateBootNextKey
) 
1375                         gIOHibernateBootNextKey 
= OSSymbol::withCString("8BE4DF61-93CA-11D2-AA0D-00E098032B8C:BootNext"); 
1376                     if (!gIOHibernateBootNextData
) 
1378                         uint16_t bits 
= 0x0082; 
1379                         gIOHibernateBootNextData 
= OSData::withBytes(&bits
, sizeof(bits
)); 
1381                     if (gIOHibernateBoot0082Key 
&& gIOHibernateBoot0082Data 
&& gIOHibernateBootNextKey 
&& gIOHibernateBootNextData
) 
1383                         gIOHibernateBootNextSave 
= gIOOptionsEntry
->copyProperty(gIOHibernateBootNextKey
); 
1384                         gIOOptionsEntry
->setProperty(gIOHibernateBoot0082Key
, gIOHibernateBoot0082Data
); 
1385                         gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextData
); 
1389 #else /* !i386 && !x86_64 */ 
1390             if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
1392                 data 
= OSData::withBytes(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
)); 
1393                 sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootImageKeyKey
); 
1395                     gIOOptionsEntry
->setProperty(sym
, data
); 
1400                 if (false && gIOHibernateBootSignature
[0]) 
1402                     data 
= OSData::withCapacity(16); 
1403                     sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey
); 
1408                         for (uint32_t i 
= 0; (c 
= gIOHibernateBootSignature
[i
]); i
++) 
1418                             value 
= (value 
<< 4) | c
; 
1420                                 data
->appendBytes(&value
, sizeof(value
)); 
1422                         gIOOptionsEntry
->setProperty(sym
, data
); 
1430             if (!vars
->haveFastBoot
) 
1432                 // set boot volume to zero 
1433                 IODTPlatformExpert 
* platform 
= OSDynamicCast(IODTPlatformExpert
, IOService::getPlatform()); 
1434                 if (platform 
&& (kIOReturnSuccess 
== platform
->readXPRAM(kXPRamAudioVolume
,  
1435                                             &vars
->saveBootAudioVolume
, sizeof(vars
->saveBootAudioVolume
)))) 
1438                     newVolume 
= vars
->saveBootAudioVolume 
& 0xf8; 
1439                     platform
->writeXPRAM(kXPRamAudioVolume
,  
1440                                             &newVolume
, sizeof(newVolume
)); 
1443 #endif /* !i386 && !x86_64 */ 
1450     IOLockLock(gFSLock
); 
1451     if ((kIOReturnSuccess 
== err
) && (kFSOpening 
== gFSState
)) 
1453         gFSState 
= kFSOpened
; 
1454         gIOHibernateVars 
= *vars
; 
1455         gFileVars 
= *vars
->fileVars
; 
1456         gIOHibernateVars
.fileVars 
= &gFileVars
; 
1457         gIOHibernateFileRef 
= gFileVars
.fileRef
; 
1458         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderSignature
; 
1459         gIOHibernateState 
= kIOHibernateStateHibernating
; 
1463         HIBLOG("hibernate file close due timeout\n"); 
1464         if (vars
->fileVars 
&& vars
->fileVars
->fileRef
) kern_close_file_for_direct_io(vars
->fileVars
->fileRef
, 0, 0, 0, 0, 0); 
1465         IOHibernateDone(vars
); 
1468     IOLockUnlock(gFSLock
); 
1470     if (vars
->fileVars
) IODelete(vars
->fileVars
, IOPolledFileIOVars
, 1); 
1471     IODelete(vars
, IOHibernateVars
, 1); 
1476 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1478 DECLARE_IOHIBERNATEPROGRESSALPHA
 
1481 ProgressInit(hibernate_graphics_t 
* display
, uint8_t * screen
, uint8_t * saveunder
, uint32_t savelen
) 
1483     uint32_t    rowBytes
, pixelShift
; 
1486     uint32_t    alpha
, in
, color
, result
; 
1488     uint32_t    saveindex
[kIOHibernateProgressCount
] = { 0 }; 
1490     rowBytes 
= display
->rowBytes
; 
1491     pixelShift 
= display
->depth 
>> 4; 
1492     if (pixelShift 
< 1) return; 
1494     screen 
+= ((display
->width
 
1495                 - kIOHibernateProgressCount 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << (pixelShift 
- 1)) 
1496         + (display
->height 
- kIOHibernateProgressOriginY 
- kIOHibernateProgressHeight
) * rowBytes
; 
1498     for (y 
= 0; y 
< kIOHibernateProgressHeight
; y
++) 
1500         out 
= screen 
+ y 
* rowBytes
; 
1501         for (blob 
= 0; blob 
< kIOHibernateProgressCount
; blob
++) 
1503             color 
= blob 
? kIOHibernateProgressDarkGray 
: kIOHibernateProgressMidGray
; 
1504             for (x 
= 0; x 
< kIOHibernateProgressWidth
; x
++) 
1506                 alpha  
= gIOHibernateProgressAlpha
[y
][x
]; 
1512                         if (1 == pixelShift
) 
1514                             in 
= *((uint16_t *)out
) & 0x1f;     // 16 
1515                             in 
= (in 
<< 3) | (in 
>> 2); 
1518                             in 
= *((uint32_t *)out
) & 0xff;     // 32 
1519                         saveunder
[blob 
* kIOHibernateProgressSaveUnderSize 
+ saveindex
[blob
]++] = in
; 
1520                         result 
= ((255 - alpha
) * in 
+ alpha 
* result 
+ 0xff) >> 8; 
1522                     if (1 == pixelShift
) 
1525                         *((uint16_t *)out
) = (result 
<< 10) | (result 
<< 5) | result
;   // 16 
1528                         *((uint32_t *)out
) = (result 
<< 16) | (result 
<< 8) | result
;   // 32 
1530                 out 
+= (1 << pixelShift
); 
1532             out 
+= (kIOHibernateProgressSpacing 
<< pixelShift
); 
1539 ProgressUpdate(hibernate_graphics_t 
* display
, uint8_t * screen
, int32_t firstBlob
, int32_t select
) 
1541     uint32_t  rowBytes
, pixelShift
; 
1543     int32_t   blob
, lastBlob
; 
1544     uint32_t  alpha
, in
, color
, result
; 
1546     uint32_t  saveindex
[kIOHibernateProgressCount
] = { 0 }; 
1548     pixelShift 
= display
->depth 
>> 4; 
1552     rowBytes 
= display
->rowBytes
; 
1554     screen 
+= ((display
->width 
 
1555             - kIOHibernateProgressCount 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << (pixelShift 
- 1)) 
1556                 + (display
->height 
- kIOHibernateProgressOriginY 
- kIOHibernateProgressHeight
) * rowBytes
; 
1558     lastBlob  
= (select 
< kIOHibernateProgressCount
) ? select 
: (kIOHibernateProgressCount 
- 1); 
1560     screen 
+= (firstBlob 
* (kIOHibernateProgressWidth 
+ kIOHibernateProgressSpacing
)) << pixelShift
; 
1562     for (y 
= 0; y 
< kIOHibernateProgressHeight
; y
++) 
1564         out 
= screen 
+ y 
* rowBytes
; 
1565         for (blob 
= firstBlob
; blob 
<= lastBlob
; blob
++) 
1567             color 
= (blob 
< select
) ? kIOHibernateProgressLightGray 
: kIOHibernateProgressMidGray
; 
1568             for (x 
= 0; x 
< kIOHibernateProgressWidth
; x
++) 
1570                 alpha  
= gIOHibernateProgressAlpha
[y
][x
]; 
1576                         in 
= display
->progressSaveUnder
[blob
][saveindex
[blob
]++]; 
1577                         result 
= ((255 - alpha
) * in 
+ alpha 
* result 
+ 0xff) / 255; 
1579                     if (1 == pixelShift
) 
1582                         *((uint16_t *)out
) = (result 
<< 10) | (result 
<< 5) | result
;   // 16 
1585                         *((uint32_t *)out
) = (result 
<< 16) | (result 
<< 8) | result
;   // 32 
1587                 out 
+= (1 << pixelShift
); 
1589             out 
+= (kIOHibernateProgressSpacing 
<< pixelShift
); 
1594 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1597 IOHibernateIOKitSleep(void) 
1599     IOReturn ret 
= kIOReturnSuccess
; 
1600     IOLockLock(gFSLock
); 
1601     if (kFSOpening 
== gFSState
) 
1603         gFSState 
= kFSTimedOut
; 
1604         HIBLOG("hibernate file open timed out\n"); 
1605         ret 
= kIOReturnTimeout
; 
1607     IOLockUnlock(gFSLock
); 
1611 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1614 IOHibernateSystemHasSlept(void) 
1616     IOReturn          ret 
= kIOReturnSuccess
; 
1617     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
1621     IOLockLock(gFSLock
); 
1622     if ((kFSOpened 
!= gFSState
) && gIOHibernateMode
) 
1624         ret 
= kIOReturnTimeout
; 
1626     IOLockUnlock(gFSLock
); 
1627     if (kIOReturnSuccess 
!= ret
) return (ret
); 
1629     if (gIOHibernateMode
) obj 
= IOService::getPMRootDomain()->copyProperty(kIOHibernatePreviewBufferKey
); 
1630     vars
->previewBuffer 
= OSDynamicCast(IOMemoryDescriptor
, obj
); 
1631     if (obj 
&& !vars
->previewBuffer
) 
1634     vars
->consoleMapping 
= NULL
; 
1635     if (vars
->previewBuffer 
&& (kIOReturnSuccess 
!= vars
->previewBuffer
->prepare())) 
1637         vars
->previewBuffer
->release(); 
1638         vars
->previewBuffer 
= 0; 
1641     if ((kIOHibernateOptionProgress 
& gIOHibernateCurrentHeader
->options
) 
1642         && vars
->previewBuffer 
 
1643         && (data 
= OSDynamicCast(OSData
,  
1644         IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey
)))) 
1646         UInt32 flags 
= *((UInt32 
*)data
->getBytesNoCopy()); 
1647         HIBPRINT("kIOHibernatePreviewActiveKey %08lx\n", (long)flags
); 
1649         IOService::getPMRootDomain()->removeProperty(kIOHibernatePreviewActiveKey
); 
1651         if (kIOHibernatePreviewUpdates 
& flags
) 
1653             PE_Video           consoleInfo
; 
1654             hibernate_graphics_t 
* graphicsInfo 
= gIOHibernateGraphicsInfo
; 
1656             IOService::getPlatform()->getConsoleInfo(&consoleInfo
); 
1658             graphicsInfo
->width    
= consoleInfo
.v_width
; 
1659             graphicsInfo
->height   
= consoleInfo
.v_height
; 
1660             graphicsInfo
->rowBytes 
= consoleInfo
.v_rowBytes
; 
1661             graphicsInfo
->depth    
= consoleInfo
.v_depth
; 
1662             vars
->consoleMapping   
= (uint8_t *) consoleInfo
.v_baseAddr
; 
1664             HIBPRINT("video %p %d %d %d\n", 
1665                         vars
->consoleMapping
, graphicsInfo
->depth
,  
1666                         graphicsInfo
->width
, graphicsInfo
->height
); 
1667             if (vars
->consoleMapping
) 
1668                         ProgressInit(graphicsInfo
, vars
->consoleMapping
, 
1669                                         &graphicsInfo
->progressSaveUnder
[0][0], sizeof(graphicsInfo
->progressSaveUnder
)); 
1673     if (gIOOptionsEntry
) 
1674         gIOOptionsEntry
->sync(); 
1679 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1681 static DeviceTreeNode 
* 
1682 MergeDeviceTree(DeviceTreeNode 
* entry
, IORegistryEntry 
* regEntry
) 
1684     DeviceTreeNodeProperty 
* prop
; 
1685     DeviceTreeNode 
*         child
; 
1686     IORegistryEntry 
*        childRegEntry
; 
1687     const char *             nameProp
; 
1688     unsigned int             propLen
, idx
; 
1690     prop 
= (DeviceTreeNodeProperty 
*) (entry 
+ 1); 
1691     for (idx 
= 0; idx 
< entry
->nProperties
; idx
++) 
1693         if (regEntry 
&& (0 != strcmp("name", prop
->name
))) 
1695             regEntry
->setProperty((const char *) prop
->name
, (void *) (prop 
+ 1), prop
->length
); 
1696 //          HIBPRINT("%s: %s, %d\n", regEntry->getName(), prop->name, prop->length); 
1698         prop 
= (DeviceTreeNodeProperty 
*) (((uintptr_t)(prop 
+ 1)) + ((prop
->length 
+ 3) & ~3)); 
1701     child 
= (DeviceTreeNode 
*) prop
; 
1702     for (idx 
= 0; idx 
< entry
->nChildren
; idx
++) 
1704         if (kSuccess 
!= DTGetProperty(child
, "name", (void **) &nameProp
, &propLen
)) 
1706         childRegEntry 
= regEntry 
? regEntry
->childFromPath(nameProp
, gIODTPlane
) : NULL
; 
1707 //      HIBPRINT("%s == %p\n", nameProp, childRegEntry); 
1708         child 
= MergeDeviceTree(child
, childRegEntry
); 
1714 IOHibernateSystemWake(void) 
1716     if (kFSOpened 
== gFSState
) 
1718         IOHibernateDone(&gIOHibernateVars
); 
1722         IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey
); 
1723         IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey
); 
1725     return (kIOReturnSuccess
); 
1729 IOHibernateDone(IOHibernateVars 
* vars
) 
1731     hibernate_teardown(vars
->page_list
, vars
->page_list_wired
, vars
->page_list_pal
); 
1733     if (vars
->videoMapping
) 
1735         if (vars
->videoMapSize
) 
1737             IOUnmapPages(kernel_map
, vars
->videoMapping
, vars
->videoMapSize
); 
1738         if (vars
->videoAllocSize
) 
1740             kmem_free(kernel_map
, trunc_page(vars
->videoMapping
), vars
->videoAllocSize
); 
1743     if (vars
->previewBuffer
) 
1745         vars
->previewBuffer
->release(); 
1746         vars
->previewBuffer 
= 0; 
1749     if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1751         IOService::getPMRootDomain()->setProperty(kIOHibernateOptionsKey
,  
1752                                             gIOHibernateCurrentHeader
->options
, 32); 
1756         IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey
); 
1759     if ((kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1760       && (kIOHibernateGfxStatusUnknown 
!= gIOHibernateGraphicsInfo
->gfxStatus
)) 
1762         IOService::getPMRootDomain()->setProperty(kIOHibernateGfxStatusKey
,  
1763                                         &gIOHibernateGraphicsInfo
->gfxStatus
, 
1764                                         sizeof(gIOHibernateGraphicsInfo
->gfxStatus
)); 
1768         IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey
); 
1774         IOPolledFileClose(vars
->fileVars
); 
1777     // invalidate nvram properties - (gIOOptionsEntry != 0) => nvram was touched 
1779 #if defined(__i386__) || defined(__x86_64__) 
1780         IOService::getPMRootDomain()->removeProperty(gIOHibernateRTCVariablesKey
); 
1781         IOService::getPMRootDomain()->removeProperty(kIOHibernateSMCVariablesKey
); 
1784          * Hibernate variable is written to NVRAM on platforms in which RtcRam 
1785          * is not backed by coin cell.  Remove Hibernate data from NVRAM. 
1787         if (gIOOptionsEntry
) { 
1789             if (gIOHibernateRTCVariablesKey
) { 
1790                 if (gIOOptionsEntry
->getProperty(gIOHibernateRTCVariablesKey
)) { 
1791                     gIOOptionsEntry
->removeProperty(gIOHibernateRTCVariablesKey
); 
1795             if (gIOHibernateBootNextKey
) 
1797                 if (gIOHibernateBootNextSave
) 
1799                     gIOOptionsEntry
->setProperty(gIOHibernateBootNextKey
, gIOHibernateBootNextSave
); 
1800                     gIOHibernateBootNextSave
->release(); 
1801                     gIOHibernateBootNextSave 
= NULL
; 
1804                     gIOOptionsEntry
->removeProperty(gIOHibernateBootNextKey
); 
1806             gIOOptionsEntry
->sync(); 
1810     if (vars
->srcBuffer
) 
1811         vars
->srcBuffer
->release(); 
1813         vars
->ioBuffer
->release(); 
1814     bzero(&gIOHibernateHandoffPages
[0], gIOHibernateHandoffPageCount 
* sizeof(gIOHibernateHandoffPages
[0])); 
1815     if (vars
->handoffBuffer
) 
1817         if (kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) 
1819             IOHibernateHandoff 
* handoff
; 
1821             for (handoff 
= (IOHibernateHandoff 
*) vars
->handoffBuffer
->getBytesNoCopy(); 
1823                  handoff 
= (IOHibernateHandoff 
*) &handoff
->data
[handoff
->bytecount
]) 
1825                 HIBPRINT("handoff %p, %x, %x\n", handoff
, handoff
->type
, handoff
->bytecount
); 
1826                 uint8_t * data 
= &handoff
->data
[0]; 
1827                 switch (handoff
->type
) 
1829                     case kIOHibernateHandoffTypeEnd
: 
1833                     case kIOHibernateHandoffTypeDeviceTree
: 
1834                         MergeDeviceTree((DeviceTreeNode 
*) data
, IOService::getServiceRoot()); 
1837                     case kIOHibernateHandoffTypeKeyStore
: 
1838 #if defined(__i386__) || defined(__x86_64__) 
1840                             IOBufferMemoryDescriptor 
* 
1841                             md 
= IOBufferMemoryDescriptor::withBytes(data
, handoff
->bytecount
, kIODirectionOutIn
); 
1844                                 IOSetKeyStoreData(md
); 
1851                         done 
= (kIOHibernateHandoffType 
!= (handoff
->type 
& 0xFFFF0000)); 
1856         vars
->handoffBuffer
->release(); 
1858     if (vars
->fileExtents
) 
1859         vars
->fileExtents
->release(); 
1861     bzero(vars
, sizeof(*vars
)); 
1863 //    gIOHibernateState = kIOHibernateStateInactive;       // leave it for post wake code to see 
1865     return (kIOReturnSuccess
); 
1869 IOHibernateSystemPostWake(void) 
1871     struct kern_direct_file_io_ref_t 
* fileRef
; 
1873     if (kFSOpened 
== gFSState
) 
1875         // invalidate & close the image file 
1876         gIOHibernateCurrentHeader
->signature 
= kIOHibernateHeaderInvalidSignature
; 
1877         if ((fileRef 
= gIOHibernateFileRef
)) 
1879             gIOHibernateFileRef 
= 0; 
1880             kern_close_file_for_direct_io(fileRef
, 
1881                                        0, (caddr_t
) gIOHibernateCurrentHeader
,  
1882                                        sizeof(IOHibernateImageHeader
), 
1883                                        sizeof(IOHibernateImageHeader
), 
1884                                        gIOHibernateCurrentHeader
->imageSize
); 
1888     return (kIOReturnSuccess
); 
1891 bool IOHibernateWasScreenLocked(void) 
1894     if ((kIOHibernateStateWakingFromHibernate 
== gIOHibernateState
) && gIOChosenEntry
) 
1897         data 
= OSDynamicCast(OSData
, gIOChosenEntry
->getProperty(kIOScreenLockStateKey
)); 
1898         if (data
) switch (*((uint32_t *)data
->getBytesNoCopy())) 
1900             case kIOScreenLockLocked
: 
1901             case kIOScreenLockFileVaultDialog
: 
1904             case kIOScreenLockNoLock
: 
1905             case kIOScreenLockUnlocked
: 
1914 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1916 SYSCTL_STRING(_kern
, OID_AUTO
, hibernatefile
,  
1917                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1918                 gIOHibernateFilename
, sizeof(gIOHibernateFilename
), ""); 
1919 SYSCTL_STRING(_kern
, OID_AUTO
, bootsignature
,  
1920                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1921                 gIOHibernateBootSignature
, sizeof(gIOHibernateBootSignature
), ""); 
1922 SYSCTL_UINT(_kern
, OID_AUTO
, hibernatemode
,  
1923                 CTLFLAG_RW 
| CTLFLAG_NOAUTO 
| CTLFLAG_KERN 
| CTLFLAG_LOCKED
, 
1924                 &gIOHibernateMode
, 0, ""); 
1927 IOHibernateSystemInit(IOPMrootDomain 
* rootDomain
) 
1929     OSData 
* data 
= OSData::withBytesNoCopy(&gIOHibernateState
, sizeof(gIOHibernateState
)); 
1932         rootDomain
->setProperty(kIOHibernateStateKey
, data
); 
1936     if (PE_parse_boot_argn("hfile", gIOHibernateFilename
, sizeof(gIOHibernateFilename
))) 
1937         gIOHibernateMode 
= kIOHibernateModeOn
; 
1939         gIOHibernateFilename
[0] = 0; 
1941     sysctl_register_oid(&sysctl__kern_hibernatefile
); 
1942     sysctl_register_oid(&sysctl__kern_bootsignature
); 
1943     sysctl_register_oid(&sysctl__kern_hibernatemode
); 
1945     gFSLock 
= IOLockAlloc(); 
1949 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1952 hibernate_setup_for_wake(void) 
1956 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1958 #define C_ASSERT(e) typedef char    __C_ASSERT__[(e) ? 1 : -1] 
1961 no_encrypt_page(vm_offset_t ppnum
) 
1963     if (pmap_is_noencrypt((ppnum_t
)ppnum
) == TRUE
) 
1970 uint32_t        wired_pages_encrypted 
= 0; 
1971 uint32_t        dirty_pages_encrypted 
= 0; 
1972 uint32_t        wired_pages_clear 
= 0; 
1975 hibernate_pal_callback(void *vars_arg
, vm_offset_t addr
) 
1977         IOHibernateVars 
*vars 
= (IOHibernateVars 
*)vars_arg
; 
1978         /* Make sure it's not in either of the save lists */ 
1979         hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
, atop_64(addr
), 1, kIOHibernatePageStateFree
); 
1981         /* Set it in the bitmap of pages owned by the PAL */ 
1982         hibernate_page_bitset(vars
->page_list_pal
, TRUE
, atop_64(addr
)); 
1985 static struct hibernate_cryptvars_t 
*local_cryptvars
; 
1988 hibernate_pal_write(void *buffer
, size_t size
) 
1990     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
1992         IOReturn err 
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *)buffer
, size
, local_cryptvars
); 
1993         if (kIOReturnSuccess 
!= err
) { 
1994                 kprintf("epic hibernate fail! %d\n", err
); 
2003 hibernate_write_image(void) 
2005     IOHibernateImageHeader 
* header 
= gIOHibernateCurrentHeader
; 
2006     IOHibernateVars 
*        vars  
= &gIOHibernateVars
; 
2007     IOPolledFileExtent 
*     fileExtents
; 
2009     C_ASSERT(sizeof(IOHibernateImageHeader
) == 512); 
2011     uint32_t     pageCount
, pagesDone
; 
2013     vm_offset_t  ppnum
, page
; 
2017     IOByteCount  pageCompressedSize
; 
2018     uint64_t     compressedSize
, uncompressedSize
; 
2019     uint64_t     image1Size 
= 0; 
2020     uint32_t     bitmap_size
; 
2021     bool         iterDone
, pollerOpen
, needEncrypt
; 
2022     uint32_t     restore1Sum
, sum
, sum1
, sum2
; 
2025     uint32_t     pageAndCount
[2]; 
2029     AbsoluteTime startTime
, endTime
; 
2030     AbsoluteTime allTime
, compTime
; 
2033     uint32_t     lastProgressStamp 
= 0; 
2034     uint32_t     progressStamp
; 
2035     uint32_t     blob
, lastBlob 
= (uint32_t) -1L; 
2037     hibernate_cryptvars_t _cryptvars
; 
2038     hibernate_cryptvars_t 
* cryptvars 
= 0; 
2040     wired_pages_encrypted 
= 0; 
2041     dirty_pages_encrypted 
= 0; 
2042     wired_pages_clear 
= 0; 
2044     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers 
|| !vars
->fileExtents
) 
2045         return (false /* sleep */ ); 
2047     if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
2048         kdebug_enable 
= save_kdebug_enable
; 
2050     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_START
, 0, 0, 0, 0, 0); 
2051     IOService::getPMRootDomain()->tracePoint(kIOPMTracePointHibernate
); 
2053     restore1Sum 
= sum1 
= sum2 
= 0; 
2055     hibernate_pal_prepare(); 
2058     // encryption data. "iv" is the "initial vector". 
2059     if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2061         static const unsigned char first_iv
[AES_BLOCK_SIZE
] 
2062         = {  0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c, 
2063              0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda }; 
2065         cryptvars 
= &gIOHibernateCryptWakeContext
; 
2066         bzero(cryptvars
, sizeof(hibernate_cryptvars_t
)); 
2067         aes_encrypt_key(vars
->cryptKey
, 
2068                         kIOHibernateAESKeySize
, 
2069                         &cryptvars
->ctx
.encrypt
); 
2070         aes_decrypt_key(vars
->cryptKey
, 
2071                         kIOHibernateAESKeySize
, 
2072                         &cryptvars
->ctx
.decrypt
); 
2074         cryptvars 
= &_cryptvars
; 
2075         bzero(cryptvars
, sizeof(hibernate_cryptvars_t
)); 
2076         for (pageCount 
= 0; pageCount 
< sizeof(vars
->wiredCryptKey
); pageCount
++) 
2077             vars
->wiredCryptKey
[pageCount
] ^= vars
->volumeCryptKey
[pageCount
]; 
2078         bzero(&vars
->volumeCryptKey
[0], sizeof(vars
->volumeCryptKey
)); 
2079         aes_encrypt_key(vars
->wiredCryptKey
, 
2080                         kIOHibernateAESKeySize
, 
2081                         &cryptvars
->ctx
.encrypt
); 
2083         bcopy(&first_iv
[0], &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
); 
2084         bzero(&vars
->wiredCryptKey
[0], sizeof(vars
->wiredCryptKey
)); 
2085         bzero(&vars
->cryptKey
[0], sizeof(vars
->cryptKey
)); 
2087         local_cryptvars 
= cryptvars
; 
2091     hibernate_setup_for_wake(); 
2093     hibernate_page_list_setall(vars
->page_list
, 
2094                                vars
->page_list_wired
, 
2095                                                            vars
->page_list_pal
, 
2098     HIBLOG("hibernate_page_list_setall found pageCount %d\n", pageCount
); 
2100     fileExtents 
= (IOPolledFileExtent 
*) vars
->fileExtents
->getBytesNoCopy(); 
2103     count 
= vars
->fileExtents
->getLength() / sizeof(IOPolledFileExtent
); 
2104     for (page 
= 0; page 
< count
; page
++) 
2106         HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page
,  
2107                 fileExtents
[page
].start
, fileExtents
[page
].length
, 
2108                 fileExtents
[page
].start 
+ fileExtents
[page
].length
); 
2112     needEncrypt 
= (0 != (kIOHibernateModeEncrypt 
& gIOHibernateMode
)); 
2113     AbsoluteTime_to_scalar(&compTime
) = 0; 
2116     clock_get_uptime(&allTime
); 
2117     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2118                         kIOPMStatsHibernateImageWrite 
| kIOPMStatsEventStartFlag
, allTime
); 
2123         uncompressedSize 
= 0; 
2125         IOPolledFileSeek(vars
->fileVars
, sizeof(IOHibernateImageHeader
)); 
2127         HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n",  
2128                 ml_get_interrupts_enabled()); 
2129         err 
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledBeforeSleepState
, vars
->ioBuffer
); 
2130         HIBLOG("IOHibernatePollerOpen(%x)\n", err
); 
2131         pollerOpen 
= (kIOReturnSuccess 
== err
); 
2135         // copy file block extent list if larger than header 
2137         count 
= vars
->fileExtents
->getLength(); 
2138         if (count 
> sizeof(header
->fileExtentMap
)) 
2140             count 
-= sizeof(header
->fileExtentMap
); 
2141             err 
= IOPolledFileWrite(vars
->fileVars
, 
2142                                     ((uint8_t *) &fileExtents
[0]) + sizeof(header
->fileExtentMap
), count
, cryptvars
); 
2143             if (kIOReturnSuccess 
!= err
) 
2147         uintptr_t hibernateBase
; 
2148         uintptr_t hibernateEnd
; 
2150         hibernateBase 
= HIB_BASE
; /* Defined in PAL headers */ 
2152         hibernateEnd 
= (segHIBB 
+ segSizeHIB
); 
2154         // copy out restore1 code 
2157             (phys64 
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2160             for (pagesDone 
= 0; pagesDone 
< atop_32(segLen
); pagesDone
++) 
2162                 gIOHibernateHandoffPages
[atop_32(count
) + pagesDone
] = atop_64(phys64
) + pagesDone
; 
2166         page 
= atop_32(kvtophys(hibernateBase
)); 
2167         count 
= atop_32(round_page(hibernateEnd
) - hibernateBase
); 
2168         header
->restore1CodePhysPage 
= page
; 
2169         header
->restore1CodeVirt 
= hibernateBase
; 
2170         header
->restore1PageCount 
= count
; 
2171         header
->restore1CodeOffset 
= ((uintptr_t) &hibernate_machine_entrypoint
)      - hibernateBase
; 
2172         header
->restore1StackOffset 
= ((uintptr_t) &gIOHibernateRestoreStackEnd
[0]) - 64 - hibernateBase
; 
2174         // sum __HIB seg, with zeros for the stack 
2175         src 
= (uint8_t *) trunc_page(hibernateBase
); 
2176         for (page 
= 0; page 
< count
; page
++) 
2178             if ((src 
< &gIOHibernateRestoreStack
[0]) || (src 
>= &gIOHibernateRestoreStackEnd
[0])) 
2179                 restore1Sum 
+= hibernate_sum_page(src
, header
->restore1CodeVirt 
+ page
); 
2181                 restore1Sum 
+= 0x00000000; 
2186         // write the __HIB seg, with zeros for the stack 
2188         src 
= (uint8_t *) trunc_page(hibernateBase
); 
2189         count 
= ((uintptr_t) &gIOHibernateRestoreStack
[0]) - trunc_page(hibernateBase
); 
2192             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2193             if (kIOReturnSuccess 
!= err
) 
2196         err 
= IOPolledFileWrite(vars
->fileVars
,  
2198                                         &gIOHibernateRestoreStackEnd
[0] - &gIOHibernateRestoreStack
[0], 
2200         if (kIOReturnSuccess 
!= err
) 
2202         src 
= &gIOHibernateRestoreStackEnd
[0]; 
2203         count 
= round_page(hibernateEnd
) - ((uintptr_t) src
); 
2206             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2207             if (kIOReturnSuccess 
!= err
) 
2211         vars
->fileVars
->encryptStart 
= (vars
->fileVars
->position 
& ~(AES_BLOCK_SIZE 
- 1)); 
2212         vars
->fileVars
->encryptEnd   
= UINT64_MAX
; 
2213         HIBLOG("encryptStart %qx\n", vars
->fileVars
->encryptStart
); 
2215         // write the preview buffer 
2217         if (vars
->previewBuffer
) 
2223                 phys64 
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
); 
2224                 pageAndCount
[0] = atop_64(phys64
); 
2225                 pageAndCount
[1] = atop_32(segLen
); 
2226                 err 
= IOPolledFileWrite(vars
->fileVars
,  
2227                                         (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),  
2229                 if (kIOReturnSuccess 
!= err
) 
2232                 ppnum 
+= sizeof(pageAndCount
); 
2235             if (kIOReturnSuccess 
!= err
) 
2238             src 
= (uint8_t *) vars
->previewBuffer
->getPhysicalSegment(0, NULL
, _kIOMemorySourceSegment
); 
2240                         ((hibernate_preview_t 
*)src
)->lockTime 
= gIOConsoleLockTime
; 
2242             count 
= vars
->previewBuffer
->getLength(); 
2244             header
->previewPageListSize 
= ppnum
; 
2245             header
->previewSize 
= count 
+ ppnum
; 
2247             for (page 
= 0; page 
< count
; page 
+= page_size
) 
2249                 phys64 
= vars
->previewBuffer
->getPhysicalSegment(page
, NULL
, kIOMemoryMapperNone
); 
2250                 sum1 
+= hibernate_sum_page(src 
+ page
, atop_64(phys64
)); 
2252             err 
= IOPolledFileWrite(vars
->fileVars
, src
, count
, cryptvars
); 
2253             if (kIOReturnSuccess 
!= err
) 
2257         // mark areas for no save 
2260             (phys64 
= vars
->ioBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2263             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2264                                         atop_64(phys64
), atop_32(segLen
), 
2265                                         kIOHibernatePageStateFree
); 
2266             pageCount 
-= atop_32(segLen
); 
2270             (phys64 
= vars
->srcBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2273             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2274                                         atop_64(phys64
), atop_32(segLen
), 
2275                                         kIOHibernatePageStateFree
); 
2276             pageCount 
-= atop_32(segLen
); 
2279         // copy out bitmap of pages available for trashing during restore 
2281         bitmap_size 
= vars
->page_list_wired
->list_size
; 
2282         src 
= (uint8_t *) vars
->page_list_wired
; 
2283         err 
= IOPolledFileWrite(vars
->fileVars
, src
, bitmap_size
, cryptvars
); 
2284         if (kIOReturnSuccess 
!= err
) 
2287         // mark more areas for no save, but these are not available  
2288         // for trashing during restore 
2290         hibernate_page_list_set_volatile(vars
->page_list
, vars
->page_list_wired
, &pageCount
); 
2293         page 
= atop_32(KERNEL_IMAGE_TO_PHYS(hibernateBase
)); 
2294         count 
= atop_32(round_page(KERNEL_IMAGE_TO_PHYS(hibernateEnd
))) - page
; 
2295         hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
, 
2297                                         kIOHibernatePageStateFree
); 
2300         if (vars
->previewBuffer
) for (count 
= 0; 
2301                                         (phys64 
= vars
->previewBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2304             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2305                                         atop_64(phys64
), atop_32(segLen
), 
2306                                         kIOHibernatePageStateFree
); 
2307             pageCount 
-= atop_32(segLen
); 
2311             (phys64 
= vars
->handoffBuffer
->getPhysicalSegment(count
, &segLen
, kIOMemoryMapperNone
)); 
2314             hibernate_set_page_state(vars
->page_list
, vars
->page_list_wired
,  
2315                                         atop_64(phys64
), atop_32(segLen
), 
2316                                         kIOHibernatePageStateFree
); 
2317             pageCount 
-= atop_32(segLen
); 
2320                 (void)hibernate_pal_callback
; 
2322         src 
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy(); 
2327         HIBLOG("writing %d pages\n", pageCount
); 
2334             kWiredEncrypt   
= kWired 
| kEncrypt
, 
2335             kWiredClear     
= kWired
, 
2336             kUnwiredEncrypt 
= kEncrypt
 
2339         for (pageType 
= kWiredEncrypt
; pageType 
>= kUnwiredEncrypt
; pageType
--) 
2341             if (kUnwiredEncrypt 
== pageType
) 
2343                 // start unwired image 
2344                 vars
->fileVars
->encryptStart 
= (vars
->fileVars
->position 
& ~(((uint64_t)AES_BLOCK_SIZE
) - 1)); 
2345                 vars
->fileVars
->encryptEnd   
= UINT64_MAX
; 
2346                 HIBLOG("encryptStart %qx\n", vars
->fileVars
->encryptStart
); 
2347                 bcopy(&cryptvars
->aes_iv
[0],  
2348                         &gIOHibernateCryptWakeContext
.aes_iv
[0],  
2349                         sizeof(cryptvars
->aes_iv
)); 
2350                 cryptvars 
= &gIOHibernateCryptWakeContext
; 
2352             for (iterDone 
= false, ppnum 
= 0; !iterDone
; ) 
2354                 count 
= hibernate_page_list_iterate((kWired 
& pageType
)  
2355                                                             ? vars
->page_list_wired 
: vars
->page_list
, 
2357 //              kprintf("[%d](%x : %x)\n", pageType, ppnum, count); 
2360                 if (count 
&& (kWired 
& pageType
) && needEncrypt
) 
2362                     uint32_t checkIndex
; 
2363                     for (checkIndex 
= 0; 
2364                             (checkIndex 
< count
)  
2365                                 && (((kEncrypt 
& pageType
) == 0) == no_encrypt_page(ppnum 
+ checkIndex
));  
2378                     case kWiredEncrypt
:   wired_pages_encrypted 
+= count
; break; 
2379                     case kWiredClear
:     wired_pages_clear     
+= count
; break; 
2380                     case kUnwiredEncrypt
: dirty_pages_encrypted 
+= count
; break; 
2383                 if (iterDone 
&& (kWiredEncrypt 
== pageType
))   {/* not yet end of wired list */} 
2386                     pageAndCount
[0] = ppnum
; 
2387                     pageAndCount
[1] = count
; 
2388                     err 
= IOPolledFileWrite(vars
->fileVars
,  
2389                                             (const uint8_t *) &pageAndCount
, sizeof(pageAndCount
),  
2391                     if (kIOReturnSuccess 
!= err
) 
2395                 for (page 
= ppnum
; page 
< (ppnum 
+ count
); page
++) 
2397                     err 
= IOMemoryDescriptorWriteFromPhysical(vars
->srcBuffer
, 0, ptoa_64(page
), page_size
); 
2400                         HIBLOG("IOMemoryDescriptorWriteFromPhysical %d [%ld] %x\n", __LINE__
, (long)page
, err
); 
2404                     sum 
= hibernate_sum_page(src
, page
); 
2405                     if (kWired 
& pageType
) 
2410                     clock_get_uptime(&startTime
); 
2412                     pageCompressedSize 
= WKdm_compress ((WK_word
*) src
, (WK_word
*) (src 
+ page_size
), PAGE_SIZE_IN_WORDS
); 
2414                     clock_get_uptime(&endTime
); 
2415                     ADD_ABSOLUTETIME(&compTime
, &endTime
); 
2416                     SUB_ABSOLUTETIME(&compTime
, &startTime
); 
2417                     compBytes 
+= page_size
; 
2419                     if (kIOHibernateModeEncrypt 
& gIOHibernateMode
) 
2420                         pageCompressedSize 
= (pageCompressedSize 
+ AES_BLOCK_SIZE 
- 1) & ~(AES_BLOCK_SIZE 
- 1); 
2422                     if (pageCompressedSize 
> page_size
) 
2424 //                      HIBLOG("------------lose: %d\n", pageCompressedSize); 
2425                         pageCompressedSize 
= page_size
; 
2428                     if (pageCompressedSize 
!= page_size
) 
2429                         data 
= (src 
+ page_size
); 
2433                     tag 
= pageCompressedSize 
| kIOHibernateTagSignature
; 
2434                     err 
= IOPolledFileWrite(vars
->fileVars
, (const uint8_t *) &tag
, sizeof(tag
), cryptvars
); 
2435                     if (kIOReturnSuccess 
!= err
) 
2438                     err 
= IOPolledFileWrite(vars
->fileVars
, data
, (pageCompressedSize 
+ 3) & ~3, cryptvars
); 
2439                     if (kIOReturnSuccess 
!= err
) 
2442                     compressedSize 
+= pageCompressedSize
; 
2443                     if (pageCompressedSize
) 
2444                         uncompressedSize 
+= page_size
; 
2447                     if (vars
->consoleMapping 
&& (0 == (1023 & pagesDone
))) 
2449                         blob 
= ((pagesDone 
* kIOHibernateProgressCount
) / pageCount
); 
2450                         if (blob 
!= lastBlob
) 
2452                             ProgressUpdate(gIOHibernateGraphicsInfo
, vars
->consoleMapping
, lastBlob
, blob
); 
2456                     if (0 == (8191 & pagesDone
)) 
2458                         clock_get_uptime(&endTime
); 
2459                         SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2460                         absolutetime_to_nanoseconds(endTime
, &nsec
); 
2461                         progressStamp 
= nsec 
/ 750000000ULL; 
2462                         if (progressStamp 
!= lastProgressStamp
) 
2464                             lastProgressStamp 
= progressStamp
; 
2465                             HIBPRINT("pages %d (%d%%)\n", pagesDone
, (100 * pagesDone
) / pageCount
); 
2469                 if (kIOReturnSuccess 
!= err
) 
2474             if (kIOReturnSuccess 
!= err
) 
2477             if ((kEncrypt 
& pageType
)) 
2479                 vars
->fileVars
->encryptEnd 
= ((vars
->fileVars
->position 
+ 511) & ~511ULL); 
2480                 HIBLOG("encryptEnd %qx\n", vars
->fileVars
->encryptEnd
); 
2483             if (kWiredEncrypt 
!= pageType
) 
2485                 // end of image1/2 - fill to next block 
2486                 err 
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
); 
2487                 if (kIOReturnSuccess 
!= err
) 
2490             if (kWiredClear 
== pageType
) 
2492                 // enlarge wired image for test 
2493 //              err = IOPolledFileWrite(vars->fileVars, 0, 0x60000000, cryptvars); 
2496                 header
->encryptStart 
= vars
->fileVars
->encryptStart
; 
2497                 header
->encryptEnd   
= vars
->fileVars
->encryptEnd
; 
2498                 image1Size 
= vars
->fileVars
->position
; 
2499                 HIBLOG("image1Size 0x%qx, encryptStart1 0x%qx, End1 0x%qx\n", 
2500                         image1Size
, header
->encryptStart
, header
->encryptEnd
); 
2503         if (kIOReturnSuccess 
!= err
) 
2508         header
->imageSize    
= vars
->fileVars
->position
; 
2509         header
->image1Size   
= image1Size
; 
2510         header
->bitmapSize   
= bitmap_size
; 
2511         header
->pageCount    
= pageCount
; 
2513         header
->restore1Sum  
= restore1Sum
; 
2514         header
->image1Sum    
= sum1
; 
2515         header
->image2Sum    
= sum2
; 
2516         header
->sleepTime    
= gIOLastSleepTime
.tv_sec
; 
2518         count 
= vars
->fileExtents
->getLength(); 
2519         if (count 
> sizeof(header
->fileExtentMap
)) 
2521             header
->fileExtentMapSize 
= count
; 
2522             count 
= sizeof(header
->fileExtentMap
); 
2525             header
->fileExtentMapSize 
= sizeof(header
->fileExtentMap
); 
2526         bcopy(&fileExtents
[0], &header
->fileExtentMap
[0], count
); 
2528         header
->deviceBase 
= vars
->fileVars
->block0
; 
2530         IOPolledFileSeek(vars
->fileVars
, 0); 
2531         err 
= IOPolledFileWrite(vars
->fileVars
, 
2532                                     (uint8_t *) header
, sizeof(IOHibernateImageHeader
),  
2534         if (kIOReturnSuccess 
!= err
) 
2536         err 
= IOPolledFileWrite(vars
->fileVars
, 0, 0, cryptvars
); 
2537         if (kIOReturnSuccess 
!= err
) 
2539         err 
= IOHibernatePollerIODone(vars
->fileVars
, true); 
2540         if (kIOReturnSuccess 
!= err
) 
2545     clock_get_uptime(&endTime
); 
2547     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2548                         kIOPMStatsHibernateImageWrite 
| kIOPMStatsEventStopFlag
, endTime
); 
2550     SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2551     absolutetime_to_nanoseconds(endTime
, &nsec
); 
2552     HIBLOG("all time: %qd ms, ",  
2555     absolutetime_to_nanoseconds(compTime
, &nsec
); 
2556     HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",  
2559                 nsec 
? (((compBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2561     absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
); 
2562     HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s, ",  
2563                 vars
->fileVars
->cryptBytes
,  
2565                 nsec 
? (((vars
->fileVars
->cryptBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2567     HIBLOG("\nimage %qd, uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n",  
2569                uncompressedSize
, atop_32(uncompressedSize
), compressedSize
, 
2570                uncompressedSize 
? ((int) ((compressedSize 
* 100ULL) / uncompressedSize
)) : 0, 
2573     HIBLOG("wired_pages_encrypted %d, wired_pages_clear %d, dirty_pages_encrypted %d\n",  
2574              wired_pages_encrypted
, wired_pages_clear
, dirty_pages_encrypted
); 
2576     if (vars
->fileVars
->io
) 
2577         (void) IOHibernatePollerIODone(vars
->fileVars
, false); 
2580         IOHibernatePollerClose(vars
->fileVars
, kIOPolledBeforeSleepState
); 
2582     if (vars
->consoleMapping
) 
2583         ProgressUpdate(gIOHibernateGraphicsInfo
,  
2584                         vars
->consoleMapping
, 0, kIOHibernateProgressCount
); 
2586     HIBLOG("hibernate_write_image done(%x)\n", err
); 
2588     // should we come back via regular wake, set the state in memory. 
2589     gIOHibernateState 
= kIOHibernateStateInactive
; 
2591     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 1) | DBG_FUNC_END
, 
2592                           wired_pages_encrypted
, wired_pages_clear
, dirty_pages_encrypted
, 0, 0); 
2594     if (kIOReturnSuccess 
== err
) 
2596         if (kIOHibernateModeSleep 
& gIOHibernateMode
) 
2598             return (kIOHibernatePostWriteSleep
); 
2600         else if(kIOHibernateModeRestart 
& gIOHibernateMode
) 
2602             return (kIOHibernatePostWriteRestart
); 
2606             /* by default, power down */ 
2607             return (kIOHibernatePostWriteHalt
); 
2610     else if (kIOReturnAborted 
== err
) 
2612         return (kIOHibernatePostWriteWake
); 
2616         /* on error, sleep */ 
2617         return (kIOHibernatePostWriteSleep
); 
2621 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2624 hibernate_machine_init(void) 
2629     uint32_t     pagesRead 
= 0; 
2630     AbsoluteTime startTime
, compTime
; 
2631     AbsoluteTime allTime
, endTime
; 
2634     uint32_t     lastProgressStamp 
= 0; 
2635     uint32_t     progressStamp
; 
2636     hibernate_cryptvars_t 
* cryptvars 
= 0; 
2638     IOHibernateVars 
* vars  
= &gIOHibernateVars
; 
2640     if (!vars
->fileVars 
|| !vars
->fileVars
->pollers 
|| !vars
->fileExtents
) 
2643     sum 
= gIOHibernateCurrentHeader
->actualImage1Sum
; 
2644     pagesDone 
= gIOHibernateCurrentHeader
->actualUncompressedPages
; 
2646     HIBLOG("hibernate_machine_init: state %d, image pages %d, sum was %x, image1Size %qx, conflictCount %d, nextFree %x\n", 
2647             gIOHibernateState
, pagesDone
, sum
, gIOHibernateCurrentHeader
->image1Size
, 
2648             gIOHibernateCurrentHeader
->conflictCount
, gIOHibernateCurrentHeader
->nextFree
); 
2650     if (kIOHibernateStateWakingFromHibernate 
!= gIOHibernateState
) 
2652         HIBLOG("regular wake\n"); 
2656     HIBPRINT("diag %x %x %x %x\n", 
2657             gIOHibernateCurrentHeader
->diag
[0], gIOHibernateCurrentHeader
->diag
[1],  
2658             gIOHibernateCurrentHeader
->diag
[2], gIOHibernateCurrentHeader
->diag
[3]); 
2660     if ((kIOHibernateModeDiscardCleanActive 
| kIOHibernateModeDiscardCleanInactive
) & gIOHibernateMode
) 
2661         hibernate_page_list_discard(vars
->page_list
); 
2663     cryptvars 
= (kIOHibernateModeEncrypt 
& gIOHibernateMode
) ? &gIOHibernateCryptWakeContext 
: 0; 
2665     if (gIOHibernateCurrentHeader
->handoffPageCount 
> gIOHibernateHandoffPageCount
) 
2666         panic("handoff overflow"); 
2668     IOHibernateHandoff 
* handoff
; 
2670     bool                 foundCryptData 
= false; 
2672     for (handoff 
= (IOHibernateHandoff 
*) vars
->handoffBuffer
->getBytesNoCopy(); 
2674          handoff 
= (IOHibernateHandoff 
*) &handoff
->data
[handoff
->bytecount
]) 
2676 //      HIBPRINT("handoff %p, %x, %x\n", handoff, handoff->type, handoff->bytecount); 
2677         uint8_t * data 
= &handoff
->data
[0]; 
2678         switch (handoff
->type
) 
2680             case kIOHibernateHandoffTypeEnd
: 
2684             case kIOHibernateHandoffTypeGraphicsInfo
: 
2685                 bcopy(data
, gIOHibernateGraphicsInfo
, sizeof(*gIOHibernateGraphicsInfo
)); 
2688             case kIOHibernateHandoffTypeCryptVars
: 
2691                     hibernate_cryptwakevars_t 
* 
2692                     wakevars 
= (hibernate_cryptwakevars_t 
*) &handoff
->data
[0]; 
2693                     bcopy(&wakevars
->aes_iv
[0], &cryptvars
->aes_iv
[0], sizeof(cryptvars
->aes_iv
)); 
2695                 foundCryptData 
= true; 
2696                 bzero(data
, handoff
->bytecount
); 
2699             case kIOHibernateHandoffTypeMemoryMap
: 
2700                 hibernate_newruntime_map(data
, handoff
->bytecount
,  
2701                                          gIOHibernateCurrentHeader
->systemTableOffset
); 
2704             case kIOHibernateHandoffTypeDeviceTree
: 
2706 //                  DTEntry chosen = NULL; 
2707 //                  HIBPRINT("DTLookupEntry %d\n", DTLookupEntry((const DTEntry) data, "/chosen", &chosen)); 
2712                 done 
= (kIOHibernateHandoffType 
!= (handoff
->type 
& 0xFFFF0000)); 
2716     if (cryptvars 
&& !foundCryptData
) 
2717         panic("hibernate handoff"); 
2719     HIBPRINT("video %x %d %d %d status %x\n", 
2720             gIOHibernateGraphicsInfo
->physicalAddress
, gIOHibernateGraphicsInfo
->depth
,  
2721             gIOHibernateGraphicsInfo
->width
, gIOHibernateGraphicsInfo
->height
, gIOHibernateGraphicsInfo
->gfxStatus
);  
2723     if (vars
->videoMapping 
&& gIOHibernateGraphicsInfo
->physicalAddress
) 
2725         vars
->videoMapSize 
= round_page(gIOHibernateGraphicsInfo
->height 
 
2726                                         * gIOHibernateGraphicsInfo
->rowBytes
); 
2727         IOMapPages(kernel_map
,  
2728                     vars
->videoMapping
, gIOHibernateGraphicsInfo
->physicalAddress
, 
2729                     vars
->videoMapSize
, kIOMapInhibitCache 
); 
2732     if (vars
->videoMapSize
) 
2733         ProgressUpdate(gIOHibernateGraphicsInfo
,  
2734                         (uint8_t *) vars
->videoMapping
, 0, kIOHibernateProgressCount
); 
2736     uint8_t * src 
= (uint8_t *) vars
->srcBuffer
->getBytesNoCopy(); 
2737     uint32_t decoOffset
; 
2739     clock_get_uptime(&allTime
); 
2740     AbsoluteTime_to_scalar(&compTime
) = 0; 
2743     HIBLOG("IOHibernatePollerOpen(), ml_get_interrupts_enabled %d\n", ml_get_interrupts_enabled()); 
2744     err 
= IOHibernatePollerOpen(vars
->fileVars
, kIOPolledAfterSleepState
, 0); 
2745     HIBLOG("IOHibernatePollerOpen(%x)\n", err
); 
2747     IOPolledFileSeek(vars
->fileVars
, gIOHibernateCurrentHeader
->image1Size
); 
2749     // kick off the read ahead 
2750     vars
->fileVars
->io           
= false; 
2751     vars
->fileVars
->bufferHalf   
= 0; 
2752     vars
->fileVars
->bufferLimit  
= 0; 
2753     vars
->fileVars
->lastRead     
= 0; 
2754     vars
->fileVars
->readEnd      
= gIOHibernateCurrentHeader
->imageSize
; 
2755     vars
->fileVars
->bufferOffset 
= vars
->fileVars
->bufferLimit
; 
2756     vars
->fileVars
->cryptBytes   
= 0; 
2757     AbsoluteTime_to_scalar(&vars
->fileVars
->cryptTime
) = 0; 
2759     err 
= IOPolledFileRead(vars
->fileVars
, 0, 0, cryptvars
); 
2760     vars
->fileVars
->bufferOffset 
= vars
->fileVars
->bufferLimit
; 
2763     HIBLOG("hibernate_machine_init reading\n"); 
2765     uint32_t * header 
= (uint32_t *) src
; 
2768     while (kIOReturnSuccess 
== err
) 
2773         vm_offset_t  ppnum
, compressedSize
; 
2775         err 
= IOPolledFileRead(vars
->fileVars
, src
, 8, cryptvars
); 
2776         if (kIOReturnSuccess 
!= err
) 
2782 //      HIBPRINT("(%x, %x)\n", ppnum, count); 
2787         for (page 
= 0; page 
< count
; page
++) 
2789             err 
= IOPolledFileRead(vars
->fileVars
, (uint8_t *) &tag
, 4, cryptvars
); 
2790             if (kIOReturnSuccess 
!= err
) 
2793             compressedSize 
= kIOHibernateTagLength 
& tag
; 
2794             if (kIOHibernateTagSignature 
!= (tag 
& ~kIOHibernateTagLength
)) 
2796                 err 
= kIOReturnIPCError
; 
2800             if (!compressedSize
) 
2807             err 
= IOPolledFileRead(vars
->fileVars
, src
, (compressedSize 
+ 3) & ~3, cryptvars
); 
2808             if (kIOReturnSuccess 
!= err
) 
2811             if (compressedSize 
< page_size
) 
2813                 decoOffset 
= page_size
; 
2815                 clock_get_uptime(&startTime
); 
2816                 WKdm_decompress((WK_word
*) src
, (WK_word
*) (src 
+ decoOffset
), PAGE_SIZE_IN_WORDS
); 
2817                 clock_get_uptime(&endTime
); 
2818                 ADD_ABSOLUTETIME(&compTime
, &endTime
); 
2819                 SUB_ABSOLUTETIME(&compTime
, &startTime
); 
2821                 compBytes 
+= page_size
; 
2826             sum 
+= hibernate_sum_page((src 
+ decoOffset
), ppnum
); 
2828             err 
= IOMemoryDescriptorReadToPhysical(vars
->srcBuffer
, decoOffset
, ptoa_64(ppnum
), page_size
); 
2831                 HIBLOG("IOMemoryDescriptorReadToPhysical [%ld] %x\n", (long)ppnum
, err
); 
2839             if (0 == (8191 & pagesDone
)) 
2841                 clock_get_uptime(&endTime
); 
2842                 SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2843                 absolutetime_to_nanoseconds(endTime
, &nsec
); 
2844                 progressStamp 
= nsec 
/ 750000000ULL; 
2845                 if (progressStamp 
!= lastProgressStamp
) 
2847                     lastProgressStamp 
= progressStamp
; 
2848                     HIBPRINT("pages %d (%d%%)\n", pagesDone
,  
2849                             (100 * pagesDone
) / gIOHibernateCurrentHeader
->pageCount
); 
2854     if ((kIOReturnSuccess 
== err
) && (pagesDone 
== gIOHibernateCurrentHeader
->actualUncompressedPages
)) 
2855         err 
= kIOReturnLockedRead
; 
2857     if (kIOReturnSuccess 
!= err
) 
2858         panic("Hibernate restore error %x", err
); 
2860     gIOHibernateCurrentHeader
->actualImage2Sum 
= sum
; 
2862     if (vars
->fileVars
->io
) 
2863         (void) IOHibernatePollerIODone(vars
->fileVars
, false); 
2865     err 
= IOHibernatePollerClose(vars
->fileVars
, kIOPolledAfterSleepState
); 
2867     clock_get_uptime(&endTime
); 
2869     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2870                         kIOPMStatsHibernateImageRead 
| kIOPMStatsEventStartFlag
, allTime
); 
2871     IOService::getPMRootDomain()->pmStatsRecordEvent(  
2872                         kIOPMStatsHibernateImageRead 
| kIOPMStatsEventStopFlag
, endTime
); 
2874     SUB_ABSOLUTETIME(&endTime
, &allTime
); 
2875     absolutetime_to_nanoseconds(endTime
, &nsec
); 
2877     HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %qd ms, ",  
2878                 pagesDone
, sum
, nsec 
/ 1000000ULL); 
2880     absolutetime_to_nanoseconds(compTime
, &nsec
); 
2881     HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ",  
2884                 nsec 
? (((compBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2886     absolutetime_to_nanoseconds(vars
->fileVars
->cryptTime
, &nsec
); 
2887     HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s\n",  
2888                 vars
->fileVars
->cryptBytes
,  
2890                 nsec 
? (((vars
->fileVars
->cryptBytes 
* 1000000000ULL) / 1024 / 1024) / nsec
) : 0); 
2892     KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 2) | DBG_FUNC_NONE
, pagesRead
, pagesDone
, 0, 0, 0); 
2895 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
2897 void IOHibernateSystemRestart(void) 
2899     static uint8_t    noteStore
[32] __attribute__((aligned(32))); 
2900     IORegistryEntry 
* regEntry
; 
2901     const OSSymbol 
*  sym
; 
2904     uintptr_t *       smcVars
; 
2909     data 
= OSDynamicCast(OSData
, IOService::getPMRootDomain()->getProperty(kIOHibernateSMCVariablesKey
)); 
2912     smcVars 
= (typeof(smcVars
)) data
->getBytesNoCopy(); 
2913     smcBytes 
= (typeof(smcBytes
)) smcVars
[1]; 
2915     if (len 
> sizeof(noteStore
)) len 
= sizeof(noteStore
); 
2916     noteProp 
= OSData::withCapacity(3 * sizeof(element
)); 
2917     if (!noteProp
) return; 
2919     noteProp
->appendBytes(&element
, sizeof(element
)); 
2920     element 
= crc32(0, smcBytes
, len
); 
2921     noteProp
->appendBytes(&element
, sizeof(element
)); 
2923     bcopy(smcBytes
, noteStore
, len
); 
2924     element 
= (addr64_t
) ¬eStore
[0]; 
2925     element 
= (element 
& page_mask
) | ptoa_64(pmap_find_phys(kernel_pmap
, element
)); 
2926     noteProp
->appendBytes(&element
, sizeof(element
)); 
2928     if (!gIOOptionsEntry
) 
2930         regEntry 
= IORegistryEntry::fromPath("/options", gIODTPlane
); 
2931         gIOOptionsEntry 
= OSDynamicCast(IODTNVRAM
, regEntry
); 
2932         if (regEntry 
&& !gIOOptionsEntry
) 
2933             regEntry
->release(); 
2936     sym 
= OSSymbol::withCStringNoCopy(kIOHibernateBootNoteKey
); 
2937     if (gIOOptionsEntry 
&& sym
) gIOOptionsEntry
->setProperty(sym
, noteProp
); 
2938     if (noteProp
)               noteProp
->release(); 
2939     if (sym
)                    sym
->release();