2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 #include <mach/mach_types.h>
25 #include <mach/vm_param.h>
26 #include <IOKit/IOHibernatePrivate.h>
27 #include <pexpert/boot.h>
28 #include <crypto/aes.h>
31 #include "IOHibernateInternal.h"
34 This code is linked into the kernel but part of the "__HIB" section, which means
35 its used by code running in the special context of restoring the kernel text and data
36 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
37 it calls or references needs to be careful to only touch memory also in the "__HIB" section.
40 uint32_t gIOHibernateState
;
42 static IOHibernateImageHeader _hibernateHeader
;
43 IOHibernateImageHeader
* gIOHibernateCurrentHeader
= &_hibernateHeader
;
45 static hibernate_graphics_t _hibernateGraphics
;
46 hibernate_graphics_t
* gIOHibernateGraphicsInfo
= &_hibernateGraphics
;
48 static hibernate_cryptwakevars_t _cryptWakeVars
;
49 hibernate_cryptwakevars_t
* gIOHibernateCryptWakeVars
= &_cryptWakeVars
;
52 extern void acpi_wake_prot_entry(void);
56 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
58 #define BASE 65521L /* largest prime smaller than 65536 */
60 // NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
62 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
63 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
64 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
65 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
66 #define DO16(buf) DO8(buf,0); DO8(buf,8);
69 hibernate_sum(uint8_t *buf
, int32_t len
)
71 unsigned long s1
= 1; // adler & 0xffff;
72 unsigned long s2
= 0; // (adler >> 16) & 0xffff;
76 k
= len
< NMAX
? len
: NMAX
;
90 return (s2
<< 16) | s1
;
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
96 static __inline__
unsigned int cntlzw(unsigned int num
)
99 __asm__
volatile("cntlzw %0, %1" : "=r" (result
) : "r" (num
));
103 static __inline__
unsigned int cntlzw(unsigned int num
)
106 __asm__
volatile( "bsrl %1, %0\n\t"
109 : "rm" (num
), "r" (63));
117 hibernate_page_bitset(hibernate_page_list_t
* list
, boolean_t set
, uint32_t page
)
120 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
122 for (bank
= 0; bank
< list
->bank_count
; bank
++)
124 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
126 page
-= bitmap
->first_page
;
128 bitmap
->bitmap
[page
>> 5] |= (0x80000000 >> (page
& 31));
129 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
131 bitmap
->bitmap
[page
>> 5] &= ~(0x80000000 >> (page
& 31));
132 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
135 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
140 hibernate_page_bittst(hibernate_page_list_t
* list
, uint32_t page
)
142 boolean_t result
= TRUE
;
144 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
146 for (bank
= 0; bank
< list
->bank_count
; bank
++)
148 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
150 page
-= bitmap
->first_page
;
151 result
= (0 != (bitmap
->bitmap
[page
>> 5] & (0x80000000 >> (page
& 31))));
154 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
159 // count bits clear or set (set == TRUE) starting at index page.
161 hibernate_page_list_count(hibernate_page_list_t
* list
, uint32_t set
, uint32_t page
)
163 uint32_t bank
, count
;
164 hibernate_bitmap_t
* bitmap
;
166 bitmap
= &list
->bank_bitmap
[0];
169 for (bank
= 0; bank
< list
->bank_count
; bank
++)
171 // bits between banks are "set"
172 if (set
&& (page
< bitmap
->first_page
))
174 count
+= bitmap
->first_page
- page
;
175 page
= bitmap
->first_page
;
177 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
179 uint32_t index
, bit
, bits
;
181 index
= (page
- bitmap
->first_page
) >> 5;
182 bit
= (page
- bitmap
->first_page
) & 31;
186 bits
= bitmap
->bitmap
[index
];
189 bits
= (bits
<< bit
);
190 count
+= cntlzw(bits
);
195 while (++index
< bitmap
->bitmapwords
)
197 bits
= bitmap
->bitmap
[index
];
200 count
+= cntlzw(bits
);
208 // bits between banks are "set"
210 if (bank
>= list
->bank_count
)
212 count
-= (bitmap
->last_page
+ 1);
213 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
214 count
+= bitmap
->first_page
;
220 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
228 hibernate_page_list_grab(hibernate_page_list_t
* map
, uint32_t * _nextFree
)
230 uint32_t nextFree
= *_nextFree
;
233 nextFree
= hibernate_page_list_count(map
, 0, 0);
235 *_nextFree
= nextFree
+ 1 + hibernate_page_list_count(map
, 0, nextFree
+ 1);
241 store_one_page(uint32_t procFlags
, uint32_t * src
, uint32_t compressedSize
,
242 uint32_t * buffer
, uint32_t ppnum
)
247 dst
= ptoa_64(ppnum
);
249 if (ppnum
< 0x00100000)
250 buffer
= (uint32_t *) (uint32_t) dst
;
252 if (ppnum
< atop_32(0xC0000000)) {
253 buffer
= (uint32_t *) (uint32_t) dst
;
257 if (compressedSize
!= PAGE_SIZE
)
259 WKdm_decompress((WK_word
*) src
, (WK_word
*) buffer
, PAGE_SIZE
>> 2);
263 sum
= hibernate_sum((uint8_t *) src
, PAGE_SIZE
);
265 if (((uint64_t) (uint32_t) src
) == dst
)
268 hibernate_restore_phys_page((uint64_t) (uint32_t) src
, dst
, PAGE_SIZE
, procFlags
);
274 bcopy_internal(const void *src
, void *dst
, uint32_t len
)
288 hibernate_kernel_entrypoint(IOHibernateImageHeader
* header
,
289 void * p2
, void * p3
, __unused
void * p4
)
291 typedef void (*ResetProc
)(void);
295 uint32_t * pageIndexSource
;
296 hibernate_page_list_t
* map
;
300 uint32_t conflictCount
;
301 uint32_t compressedSize
;
302 uint32_t uncompressedPages
;
303 uint32_t copyPageListHead
;
304 uint32_t * copyPageList
;
305 uint32_t copyPageIndex
;
308 uint32_t lastImagePage
;
309 uint32_t lastMapPage
;
310 uint32_t lastPageIndexPage
;
313 bcopy_internal(header
,
314 gIOHibernateCurrentHeader
,
315 sizeof(IOHibernateImageHeader
));
319 gIOHibernateGraphicsInfo
,
320 sizeof(hibernate_graphics_t
));
322 gIOHibernateGraphicsInfo
->physicalAddress
= gIOHibernateGraphicsInfo
->depth
= 0;
326 gIOHibernateCryptWakeVars
,
327 sizeof(hibernate_cryptvars_t
));
330 (((uint32_t) &header
->fileExtentMap
[0])
331 + header
->fileExtentMapSize
332 + ptoa_32(header
->restore1PageCount
));
334 if (header
->previewSize
)
336 pageIndexSource
= src
;
337 map
= (hibernate_page_list_t
*)(((uint32_t) pageIndexSource
) + header
->previewSize
);
338 src
= (uint32_t *) (((uint32_t) pageIndexSource
) + header
->previewPageListSize
);
343 map
= (hibernate_page_list_t
*) src
;
344 src
= (uint32_t *) (((uint32_t) map
) + header
->bitmapSize
);
347 lastPageIndexPage
= atop_32(src
);
349 lastImagePage
= atop_32(((uint32_t) header
) + header
->image1Size
);
351 lastMapPage
= atop_32(((uint32_t) map
) + header
->bitmapSize
);
353 // knock all the image pages to be used out of free map
354 for (ppnum
= atop_32(header
); ppnum
<= lastImagePage
; ppnum
++)
356 hibernate_page_bitset(map
, FALSE
, ppnum
);
360 buffer
= (uint32_t *) ptoa_32(hibernate_page_list_grab(map
, &nextFree
));
362 sum
= gIOHibernateCurrentHeader
->actualRestore1Sum
;
363 gIOHibernateCurrentHeader
->diag
[0] = (uint32_t) header
;
364 gIOHibernateCurrentHeader
->diag
[1] = sum
;
366 uncompressedPages
= 0;
368 copyPageListHead
= 0;
370 copyPageIndex
= PAGE_SIZE
>> 2;
372 compressedSize
= PAGE_SIZE
;
378 ppnum
= pageIndexSource
[0];
379 count
= pageIndexSource
[1];
380 pageIndexSource
+= 2;
384 src
= (uint32_t *) (((uint32_t) map
) + gIOHibernateCurrentHeader
->bitmapSize
);
399 for (page
= 0; page
< count
; page
++, ppnum
++)
404 if (!pageIndexSource
)
407 compressedSize
= kIOHibernateTagLength
& tag
;
410 conflicts
= (((ppnum
>= atop_32(map
)) && (ppnum
<= lastMapPage
))
411 || ((ppnum
>= atop_32(src
)) && (ppnum
<= lastImagePage
)));
414 conflicts
|= ((ppnum
>= atop_32(pageIndexSource
)) && (ppnum
<= lastPageIndexPage
));
419 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
420 src
, compressedSize
, buffer
, ppnum
);
430 // alloc new buffer page
431 bufferPage
= hibernate_page_list_grab(map
, &nextFree
);
433 if (copyPageIndex
> ((PAGE_SIZE
>> 2) - 3))
435 // alloc new copy list page
436 uint32_t pageListPage
= hibernate_page_list_grab(map
, &nextFree
);
439 copyPageList
[1] = pageListPage
;
441 copyPageListHead
= pageListPage
;
442 copyPageList
= (uint32_t *) ptoa_32(pageListPage
);
447 copyPageList
[copyPageIndex
++] = ppnum
;
448 copyPageList
[copyPageIndex
++] = bufferPage
;
449 copyPageList
[copyPageIndex
++] = compressedSize
;
450 copyPageList
[0] = copyPageIndex
;
452 dst
= (uint32_t *) ptoa_32(bufferPage
);
453 for (idx
= 0; idx
< ((compressedSize
+ 3) >> 2); idx
++)
456 src
+= ((compressedSize
+ 3) >> 2);
460 // -- copy back conflicts
462 copyPageList
= (uint32_t *) ptoa_32(copyPageListHead
);
465 for (copyPageIndex
= 2; copyPageIndex
< copyPageList
[0]; copyPageIndex
+= 3)
467 ppnum
= copyPageList
[copyPageIndex
+ 0];
468 src
= (uint32_t *) ptoa_32(copyPageList
[copyPageIndex
+ 1]);
469 compressedSize
= copyPageList
[copyPageIndex
+ 2];
471 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
472 src
, compressedSize
, buffer
, ppnum
);
475 copyPageList
= (uint32_t *) ptoa_32(copyPageList
[1]);
478 // -- image has been destroyed...
480 gIOHibernateCurrentHeader
->actualImage1Sum
= sum
;
481 gIOHibernateCurrentHeader
->actualUncompressedPages
= uncompressedPages
;
482 gIOHibernateCurrentHeader
->conflictCount
= conflictCount
;
483 gIOHibernateCurrentHeader
->nextFree
= nextFree
;
485 gIOHibernateState
= kIOHibernateStateWakingFromHibernate
;
489 proc
= (ResetProc
) 0x100;
490 __asm__
volatile("ori 0, 0, 0" : : );
494 proc
= (ResetProc
) acpi_wake_prot_entry
;