2 * Copyright (c) 2004-2006 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@
30 #include <mach/mach_types.h>
31 #include <mach/vm_param.h>
32 #include <IOKit/IOHibernatePrivate.h>
33 #include <IOKit/IOLib.h>
34 #include <pexpert/boot.h>
35 #include <crypto/aes.h>
36 #include <libkern/libkern.h>
39 #include "IOHibernateInternal.h"
42 This code is linked into the kernel but part of the "__HIB" section, which means
43 its used by code running in the special context of restoring the kernel text and data
44 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
45 it calls or references needs to be careful to only touch memory also in the "__HIB" section.
48 uint32_t gIOHibernateState
;
50 static IOHibernateImageHeader _hibernateHeader
;
51 IOHibernateImageHeader
* gIOHibernateCurrentHeader
= &_hibernateHeader
;
53 static hibernate_graphics_t _hibernateGraphics
;
54 hibernate_graphics_t
* gIOHibernateGraphicsInfo
= &_hibernateGraphics
;
56 static hibernate_cryptwakevars_t _cryptWakeVars
;
57 hibernate_cryptwakevars_t
* gIOHibernateCryptWakeVars
= &_cryptWakeVars
;
59 vm_offset_t gIOHibernateWakeMap
; // ppnum
60 vm_size_t gIOHibernateWakeMapSize
;
63 extern void acpi_wake_prot_entry(void);
66 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
68 #define BASE 65521L /* largest prime smaller than 65536 */
70 // NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
72 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
73 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
74 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
75 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
76 #define DO16(buf) DO8(buf,0); DO8(buf,8);
79 hibernate_sum(uint8_t *buf
, int32_t len
)
81 unsigned long s1
= 1; // adler & 0xffff;
82 unsigned long s2
= 0; // (adler >> 16) & 0xffff;
86 k
= len
< NMAX
? len
: NMAX
;
100 return (s2
<< 16) | s1
;
103 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
105 static __inline__
unsigned int cntlzw(unsigned int num
)
110 static hibernate_bitmap_t
*
111 hibernate_page_bitmap(hibernate_page_list_t
* list
, uint32_t page
)
114 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
116 for (bank
= 0; bank
< list
->bank_count
; bank
++)
118 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
120 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
122 if (bank
== list
->bank_count
)
129 hibernate_page_bitmap_pin(hibernate_page_list_t
* list
, uint32_t * pPage
)
131 uint32_t bank
, page
= *pPage
;
132 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
134 for (bank
= 0; bank
< list
->bank_count
; bank
++)
136 if (page
<= bitmap
->first_page
)
138 *pPage
= bitmap
->first_page
;
141 if (page
<= bitmap
->last_page
)
143 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
145 if (bank
== list
->bank_count
)
152 hibernate_page_bitset(hibernate_page_list_t
* list
, boolean_t set
, uint32_t page
)
154 hibernate_bitmap_t
* bitmap
;
156 bitmap
= hibernate_page_bitmap(list
, page
);
159 page
-= bitmap
->first_page
;
161 bitmap
->bitmap
[page
>> 5] |= (0x80000000 >> (page
& 31));
162 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
164 bitmap
->bitmap
[page
>> 5] &= ~(0x80000000 >> (page
& 31));
165 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
170 hibernate_page_bittst(hibernate_page_list_t
* list
, uint32_t page
)
172 boolean_t result
= TRUE
;
173 hibernate_bitmap_t
* bitmap
;
175 bitmap
= hibernate_page_bitmap(list
, page
);
178 page
-= bitmap
->first_page
;
179 result
= (0 != (bitmap
->bitmap
[page
>> 5] & (0x80000000 >> (page
& 31))));
184 // count bits clear or set (set == TRUE) starting at page.
186 hibernate_page_bitmap_count(hibernate_bitmap_t
* bitmap
, uint32_t set
, uint32_t page
)
188 uint32_t index
, bit
, bits
;
193 index
= (page
- bitmap
->first_page
) >> 5;
194 bit
= (page
- bitmap
->first_page
) & 31;
196 bits
= bitmap
->bitmap
[index
];
199 bits
= (bits
<< bit
);
201 count
+= __builtin_clz(bits
);
205 while (++index
< bitmap
->bitmapwords
)
207 bits
= bitmap
->bitmap
[index
];
212 count
+= __builtin_clz(bits
);
223 hibernate_page_list_grab(hibernate_page_list_t
* list
, uint32_t * pNextFree
)
225 uint32_t nextFree
= *pNextFree
;
226 uint32_t nextFreeInBank
;
227 hibernate_bitmap_t
* bitmap
;
229 nextFreeInBank
= nextFree
+ 1;
230 while ((bitmap
= hibernate_page_bitmap_pin(list
, &nextFreeInBank
)))
232 nextFreeInBank
+= hibernate_page_bitmap_count(bitmap
, FALSE
, nextFreeInBank
);
233 if (nextFreeInBank
<= bitmap
->last_page
)
235 *pNextFree
= nextFreeInBank
;
244 store_one_page(uint32_t procFlags
, uint32_t * src
, uint32_t compressedSize
,
245 uint32_t * buffer
, uint32_t ppnum
)
250 dst
= ptoa_64(ppnum
);
251 if (ppnum
< 0x00100000)
252 buffer
= (uint32_t *) (uint32_t) dst
;
254 if (compressedSize
!= PAGE_SIZE
)
256 WKdm_decompress((WK_word
*) src
, (WK_word
*) buffer
, PAGE_SIZE
>> 2);
260 sum
= hibernate_sum((uint8_t *) src
, PAGE_SIZE
);
262 if (((uint64_t) (uint32_t) src
) == dst
)
265 hibernate_restore_phys_page((uint64_t) (uint32_t) src
, dst
, PAGE_SIZE
, procFlags
);
271 bcopy_internal(const void *src
, void *dst
, uint32_t len
)
284 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
287 hibernate_kernel_entrypoint(IOHibernateImageHeader
* header
,
288 void * p2
, void * p3
, void * p4
)
290 typedef void (*ResetProc
)(void);
294 uint32_t * pageIndexSource
;
295 hibernate_page_list_t
* map
;
299 uint32_t conflictCount
;
300 uint32_t compressedSize
;
301 uint32_t uncompressedPages
;
302 uint32_t copyPageListHead
;
303 uint32_t * copyPageList
;
304 uint32_t copyPageIndex
;
307 uint32_t lastImagePage
;
308 uint32_t lastMapPage
;
309 uint32_t lastPageIndexPage
;
312 C_ASSERT(sizeof(IOHibernateImageHeader
) == 512);
314 bcopy_internal(header
,
315 gIOHibernateCurrentHeader
,
316 sizeof(IOHibernateImageHeader
));
320 count
= header
->graphicsInfoOffset
;
322 p2
= (void *)(((uintptr_t) header
) - count
);
326 gIOHibernateGraphicsInfo
,
327 sizeof(hibernate_graphics_t
));
329 gIOHibernateGraphicsInfo
->physicalAddress
= gIOHibernateGraphicsInfo
->depth
= 0;
333 count
= header
->cryptVarsOffset
;
335 p3
= (void *)(((uintptr_t) header
) - count
);
339 gIOHibernateCryptWakeVars
,
340 sizeof(hibernate_cryptvars_t
));
343 (((uint32_t) &header
->fileExtentMap
[0])
344 + header
->fileExtentMapSize
345 + ptoa_32(header
->restore1PageCount
));
347 if (header
->previewSize
)
349 pageIndexSource
= src
;
350 map
= (hibernate_page_list_t
*)(((uint32_t) pageIndexSource
) + header
->previewSize
);
351 src
= (uint32_t *) (((uint32_t) pageIndexSource
) + header
->previewPageListSize
);
356 map
= (hibernate_page_list_t
*) src
;
357 src
= (uint32_t *) (((uint32_t) map
) + header
->bitmapSize
);
360 lastPageIndexPage
= atop_32(src
);
362 lastImagePage
= atop_32(((uint32_t) header
) + header
->image1Size
);
364 lastMapPage
= atop_32(((uint32_t) map
) + header
->bitmapSize
);
366 // knock all the image pages to be used out of free map
367 for (ppnum
= atop_32(header
); ppnum
<= lastImagePage
; ppnum
++)
369 hibernate_page_bitset(map
, FALSE
, ppnum
);
373 hibernate_page_list_grab(map
, &nextFree
);
374 buffer
= (uint32_t *) ptoa_32(hibernate_page_list_grab(map
, &nextFree
));
376 if (header
->memoryMapSize
&& (count
= header
->memoryMapOffset
))
378 p4
= (void *)(((uintptr_t) header
) - count
);
379 gIOHibernateWakeMap
= hibernate_page_list_grab(map
, &nextFree
);
380 gIOHibernateWakeMapSize
= header
->memoryMapSize
;
381 bcopy_internal(p4
, (void *) ptoa_32(gIOHibernateWakeMap
), gIOHibernateWakeMapSize
);
384 gIOHibernateWakeMapSize
= 0;
386 sum
= gIOHibernateCurrentHeader
->actualRestore1Sum
;
387 gIOHibernateCurrentHeader
->diag
[0] = (uint32_t) header
;
388 gIOHibernateCurrentHeader
->diag
[1] = sum
;
390 uncompressedPages
= 0;
392 copyPageListHead
= 0;
394 copyPageIndex
= PAGE_SIZE
>> 2;
396 compressedSize
= PAGE_SIZE
;
402 ppnum
= pageIndexSource
[0];
403 count
= pageIndexSource
[1];
404 pageIndexSource
+= 2;
408 src
= (uint32_t *) (((uint32_t) map
) + gIOHibernateCurrentHeader
->bitmapSize
);
423 for (page
= 0; page
< count
; page
++, ppnum
++)
428 if (!pageIndexSource
)
431 compressedSize
= kIOHibernateTagLength
& tag
;
436 conflicts
= (((ppnum
>= atop_32(map
)) && (ppnum
<= lastMapPage
))
437 || ((ppnum
>= atop_32(src
)) && (ppnum
<= lastImagePage
)));
440 conflicts
|= ((ppnum
>= atop_32(pageIndexSource
)) && (ppnum
<= lastPageIndexPage
));
445 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
446 src
, compressedSize
, buffer
, ppnum
);
456 // alloc new buffer page
457 bufferPage
= hibernate_page_list_grab(map
, &nextFree
);
459 if (copyPageIndex
> ((PAGE_SIZE
>> 2) - 3))
461 // alloc new copy list page
462 uint32_t pageListPage
= hibernate_page_list_grab(map
, &nextFree
);
465 copyPageList
[1] = pageListPage
;
467 copyPageListHead
= pageListPage
;
468 copyPageList
= (uint32_t *) ptoa_32(pageListPage
);
473 copyPageList
[copyPageIndex
++] = ppnum
;
474 copyPageList
[copyPageIndex
++] = bufferPage
;
475 copyPageList
[copyPageIndex
++] = compressedSize
;
476 copyPageList
[0] = copyPageIndex
;
478 dst
= (uint32_t *) ptoa_32(bufferPage
);
479 for (idx
= 0; idx
< ((compressedSize
+ 3) >> 2); idx
++)
482 src
+= ((compressedSize
+ 3) >> 2);
486 // -- copy back conflicts
488 copyPageList
= (uint32_t *) ptoa_32(copyPageListHead
);
491 for (copyPageIndex
= 2; copyPageIndex
< copyPageList
[0]; copyPageIndex
+= 3)
493 ppnum
= copyPageList
[copyPageIndex
+ 0];
494 src
= (uint32_t *) ptoa_32(copyPageList
[copyPageIndex
+ 1]);
495 compressedSize
= copyPageList
[copyPageIndex
+ 2];
497 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
498 src
, compressedSize
, buffer
, ppnum
);
501 copyPageList
= (uint32_t *) ptoa_32(copyPageList
[1]);
504 // -- image has been destroyed...
506 gIOHibernateCurrentHeader
->actualImage1Sum
= sum
;
507 gIOHibernateCurrentHeader
->actualUncompressedPages
= uncompressedPages
;
508 gIOHibernateCurrentHeader
->conflictCount
= conflictCount
;
509 gIOHibernateCurrentHeader
->nextFree
= nextFree
;
511 gIOHibernateState
= kIOHibernateStateWakingFromHibernate
;
514 proc
= (ResetProc
) 0x100;
515 __asm__
volatile("ori 0, 0, 0" : : );
518 proc
= (ResetProc
) acpi_wake_prot_entry
;
523 proc
= (ResetProc
)0x00000000;