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 uint32_t gIOHibernateDebugFlags
;
52 static IOHibernateImageHeader _hibernateHeader
;
53 IOHibernateImageHeader
* gIOHibernateCurrentHeader
= &_hibernateHeader
;
55 static hibernate_graphics_t _hibernateGraphics
;
56 hibernate_graphics_t
* gIOHibernateGraphicsInfo
= &_hibernateGraphics
;
58 static hibernate_cryptwakevars_t _cryptWakeVars
;
59 hibernate_cryptwakevars_t
* gIOHibernateCryptWakeVars
= &_cryptWakeVars
;
61 vm_offset_t gIOHibernateWakeMap
; // ppnum
62 vm_size_t gIOHibernateWakeMapSize
;
66 #if defined(__i386__) || defined(__x86_64__)
67 extern void acpi_wake_prot_entry(void);
71 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
73 #if defined(__i386__) || defined(__x86_64__)
77 #include <architecture/i386/pio.h>
79 /* standard port addresses */
81 COM1_PORT_ADDR
= 0x3f8,
82 COM2_PORT_ADDR
= 0x2f8
85 /* UART register offsets */
87 UART_RBR
= 0, /* receive buffer Register (R) */
88 UART_THR
= 0, /* transmit holding register (W) */
89 UART_DLL
= 0, /* DLAB = 1, divisor latch (LSB) */
90 UART_IER
= 1, /* interrupt enable register */
91 UART_DLM
= 1, /* DLAB = 1, divisor latch (MSB) */
92 UART_IIR
= 2, /* interrupt ident register (R) */
93 UART_FCR
= 2, /* fifo control register (W) */
94 UART_LCR
= 3, /* line control register */
95 UART_MCR
= 4, /* modem control register */
96 UART_LSR
= 5, /* line status register */
97 UART_MSR
= 6, /* modem status register */
98 UART_SCR
= 7 /* scratch register */
102 UART_LCR_8BITS
= 0x03,
109 UART_MCR_OUT1
= 0x04,
110 UART_MCR_OUT2
= 0x08,
122 static void uart_putc(char c
)
124 while (!(inb(COM1_PORT_ADDR
+ UART_LSR
) & UART_LSR_THRE
))
126 outb(COM1_PORT_ADDR
+ UART_THR
, c
);
129 static int debug_probe( void )
131 /* Verify that the Scratch Register is accessible */
132 outb(COM1_PORT_ADDR
+ UART_SCR
, 0x5a);
133 if (inb(COM1_PORT_ADDR
+ UART_SCR
) != 0x5a) return false;
134 outb(COM1_PORT_ADDR
+ UART_SCR
, 0xa5);
135 if (inb(COM1_PORT_ADDR
+ UART_SCR
) != 0xa5) return false;
140 static void uart_puthex(uint64_t num
)
146 for (bit
= 60; bit
>= 0; bit
-= 4)
148 c
= 0xf & (num
>> bit
);
161 static void debug_code(uint32_t code
, uint64_t value
)
166 if (!(kIOHibernateDebugRestoreLogs
& gIOHibernateDebugFlags
))
169 for (bit
= 24; bit
>= 0; bit
-= 8)
171 c
= 0xFF & (code
>> bit
);
181 #endif /* defined(__i386__) || defined(__x86_64__) */
184 #define debug_probe() (false)
185 #define debug_code(c, v) {}
190 kIOHibernateRestoreCodeImageStart
= 'imgS',
191 kIOHibernateRestoreCodeImageEnd
= 'imgE',
192 kIOHibernateRestoreCodePageIndexStart
= 'pgiS',
193 kIOHibernateRestoreCodePageIndexEnd
= 'pgiE',
194 kIOHibernateRestoreCodeMapStart
= 'mapS',
195 kIOHibernateRestoreCodeMapEnd
= 'mapE',
196 kIOHibernateRestoreCodeWakeMapSize
= 'wkms',
197 kIOHibernateRestoreCodeConflictPage
= 'cfpg',
198 kIOHibernateRestoreCodeConflictSource
= 'cfsr',
199 kIOHibernateRestoreCodeNoMemory
= 'nomm'
202 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
205 static void fatal(void)
207 #if defined(__i386__) || defined(__x86_64__)
214 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
216 #define BASE 65521L /* largest prime smaller than 65536 */
218 // NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
220 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
221 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
222 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
223 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
224 #define DO16(buf) DO8(buf,0); DO8(buf,8);
227 hibernate_sum(uint8_t *buf
, int32_t len
)
229 unsigned long s1
= 1; // adler & 0xffff;
230 unsigned long s2
= 0; // (adler >> 16) & 0xffff;
234 k
= len
< NMAX
? len
: NMAX
;
248 return (s2
<< 16) | s1
;
251 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
253 static hibernate_bitmap_t
*
254 hibernate_page_bitmap(hibernate_page_list_t
* list
, uint32_t page
)
257 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
259 for (bank
= 0; bank
< list
->bank_count
; bank
++)
261 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
263 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
265 if (bank
== list
->bank_count
)
272 hibernate_page_bitmap_pin(hibernate_page_list_t
* list
, uint32_t * pPage
)
274 uint32_t bank
, page
= *pPage
;
275 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
277 for (bank
= 0; bank
< list
->bank_count
; bank
++)
279 if (page
<= bitmap
->first_page
)
281 *pPage
= bitmap
->first_page
;
284 if (page
<= bitmap
->last_page
)
286 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
288 if (bank
== list
->bank_count
)
295 hibernate_page_bitset(hibernate_page_list_t
* list
, boolean_t set
, uint32_t page
)
297 hibernate_bitmap_t
* bitmap
;
299 bitmap
= hibernate_page_bitmap(list
, page
);
302 page
-= bitmap
->first_page
;
304 bitmap
->bitmap
[page
>> 5] |= (0x80000000 >> (page
& 31));
305 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
307 bitmap
->bitmap
[page
>> 5] &= ~(0x80000000 >> (page
& 31));
308 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
313 hibernate_page_bittst(hibernate_page_list_t
* list
, uint32_t page
)
315 boolean_t result
= TRUE
;
316 hibernate_bitmap_t
* bitmap
;
318 bitmap
= hibernate_page_bitmap(list
, page
);
321 page
-= bitmap
->first_page
;
322 result
= (0 != (bitmap
->bitmap
[page
>> 5] & (0x80000000 >> (page
& 31))));
327 // count bits clear or set (set == TRUE) starting at page.
329 hibernate_page_bitmap_count(hibernate_bitmap_t
* bitmap
, uint32_t set
, uint32_t page
)
331 uint32_t index
, bit
, bits
;
336 index
= (page
- bitmap
->first_page
) >> 5;
337 bit
= (page
- bitmap
->first_page
) & 31;
339 bits
= bitmap
->bitmap
[index
];
342 bits
= (bits
<< bit
);
344 count
+= __builtin_clz(bits
);
348 while (++index
< bitmap
->bitmapwords
)
350 bits
= bitmap
->bitmap
[index
];
355 count
+= __builtin_clz(bits
);
366 hibernate_page_list_grab(hibernate_page_list_t
* list
, uint32_t * pNextFree
)
368 uint32_t nextFree
= *pNextFree
;
369 uint32_t nextFreeInBank
;
370 hibernate_bitmap_t
* bitmap
;
372 nextFreeInBank
= nextFree
+ 1;
373 while ((bitmap
= hibernate_page_bitmap_pin(list
, &nextFreeInBank
)))
375 nextFreeInBank
+= hibernate_page_bitmap_count(bitmap
, FALSE
, nextFreeInBank
);
376 if (nextFreeInBank
<= bitmap
->last_page
)
378 *pNextFree
= nextFreeInBank
;
385 debug_code(kIOHibernateRestoreCodeNoMemory
, nextFree
);
394 store_one_page(uint32_t procFlags
, uint32_t * src
, uint32_t compressedSize
,
395 uint32_t * buffer
, uint32_t ppnum
)
400 dst
= ptoa_64(ppnum
);
401 if (ppnum
< 0x00100000)
402 buffer
= (uint32_t *) (uintptr_t) dst
;
404 if (compressedSize
!= PAGE_SIZE
)
406 WKdm_decompress((WK_word
*) src
, (WK_word
*) buffer
, PAGE_SIZE
>> 2);
410 sum
= hibernate_sum((uint8_t *) src
, PAGE_SIZE
);
412 if (((uint64_t) (uintptr_t) src
) == dst
)
415 hibernate_restore_phys_page((uint64_t) (uintptr_t) src
, dst
, PAGE_SIZE
, procFlags
);
420 // used only for small struct copies
422 bcopy_internal(const void *src
, void *dst
, uint32_t len
)
435 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
438 hibernate_kernel_entrypoint(IOHibernateImageHeader
* header
,
439 void * p2
, void * p3
, void * p4
)
444 uint32_t * pageIndexSource
;
445 hibernate_page_list_t
* map
;
449 uint32_t conflictCount
;
450 uint32_t compressedSize
;
451 uint32_t uncompressedPages
;
452 uint32_t copyPageListHead
;
453 uint32_t * copyPageList
;
454 uint32_t copyPageIndex
;
457 uint32_t lastImagePage
;
458 uint32_t lastMapPage
;
459 uint32_t lastPageIndexPage
;
461 C_ASSERT(sizeof(IOHibernateImageHeader
) == 512);
463 if ((kIOHibernateDebugRestoreLogs
& gIOHibernateDebugFlags
) && !debug_probe())
464 gIOHibernateDebugFlags
&= ~kIOHibernateDebugRestoreLogs
;
466 debug_code(kIOHibernateRestoreCodeImageStart
, (uintptr_t) header
);
468 bcopy_internal(header
,
469 gIOHibernateCurrentHeader
,
470 sizeof(IOHibernateImageHeader
));
474 count
= header
->graphicsInfoOffset
;
476 p2
= (void *)(((uintptr_t) header
) - count
);
480 gIOHibernateGraphicsInfo
,
481 sizeof(hibernate_graphics_t
));
483 gIOHibernateGraphicsInfo
->physicalAddress
= gIOHibernateGraphicsInfo
->depth
= 0;
487 count
= header
->cryptVarsOffset
;
489 p3
= (void *)(((uintptr_t) header
) - count
);
493 gIOHibernateCryptWakeVars
,
494 sizeof(hibernate_cryptvars_t
));
497 (((uintptr_t) &header
->fileExtentMap
[0])
498 + header
->fileExtentMapSize
499 + ptoa_32(header
->restore1PageCount
));
501 if (header
->previewSize
)
503 pageIndexSource
= src
;
504 map
= (hibernate_page_list_t
*)(((uintptr_t) pageIndexSource
) + header
->previewSize
);
505 src
= (uint32_t *) (((uintptr_t) pageIndexSource
) + header
->previewPageListSize
);
510 map
= (hibernate_page_list_t
*) src
;
511 src
= (uint32_t *) (((uintptr_t) map
) + header
->bitmapSize
);
514 lastPageIndexPage
= atop_32((uintptr_t) src
);
516 lastImagePage
= atop_32(((uintptr_t) header
) + header
->image1Size
);
518 lastMapPage
= atop_32(((uintptr_t) map
) + header
->bitmapSize
);
520 debug_code(kIOHibernateRestoreCodeImageEnd
, ptoa_64(lastImagePage
));
521 debug_code(kIOHibernateRestoreCodePageIndexStart
, (uintptr_t) pageIndexSource
);
522 debug_code(kIOHibernateRestoreCodePageIndexEnd
, ptoa_64(lastPageIndexPage
));
523 debug_code(kIOHibernateRestoreCodeMapStart
, (uintptr_t) map
);
524 debug_code(kIOHibernateRestoreCodeMapEnd
, ptoa_64(lastMapPage
));
526 // knock all the image pages to be used out of free map
527 for (ppnum
= atop_32((uintptr_t) header
); ppnum
<= lastImagePage
; ppnum
++)
529 hibernate_page_bitset(map
, FALSE
, ppnum
);
533 hibernate_page_list_grab(map
, &nextFree
);
534 buffer
= (uint32_t *) (uintptr_t) ptoa_32(hibernate_page_list_grab(map
, &nextFree
));
536 if (header
->memoryMapSize
&& (count
= header
->memoryMapOffset
))
538 p4
= (void *)(((uintptr_t) header
) - count
);
539 gIOHibernateWakeMap
= hibernate_page_list_grab(map
, &nextFree
);
540 gIOHibernateWakeMapSize
= header
->memoryMapSize
;
541 debug_code(kIOHibernateRestoreCodeWakeMapSize
, gIOHibernateWakeMapSize
);
542 if (gIOHibernateWakeMapSize
> PAGE_SIZE
)
544 bcopy_internal(p4
, (void *) (uintptr_t) ptoa_32(gIOHibernateWakeMap
), gIOHibernateWakeMapSize
);
547 gIOHibernateWakeMapSize
= 0;
549 sum
= gIOHibernateCurrentHeader
->actualRestore1Sum
;
550 gIOHibernateCurrentHeader
->diag
[0] = (uint32_t)(uintptr_t) header
;
551 gIOHibernateCurrentHeader
->diag
[1] = sum
;
553 uncompressedPages
= 0;
555 copyPageListHead
= 0;
557 copyPageIndex
= PAGE_SIZE
>> 2;
559 compressedSize
= PAGE_SIZE
;
565 ppnum
= pageIndexSource
[0];
566 count
= pageIndexSource
[1];
567 pageIndexSource
+= 2;
571 src
= (uint32_t *) (((uintptr_t) map
) + gIOHibernateCurrentHeader
->bitmapSize
);
586 for (page
= 0; page
< count
; page
++, ppnum
++)
591 if (!pageIndexSource
)
594 compressedSize
= kIOHibernateTagLength
& tag
;
597 conflicts
= (((ppnum
>= atop_32((uintptr_t) map
)) && (ppnum
<= lastMapPage
))
598 || ((ppnum
>= atop_32((uintptr_t) src
)) && (ppnum
<= lastImagePage
)));
601 conflicts
|= ((ppnum
>= atop_32((uintptr_t) pageIndexSource
)) && (ppnum
<= lastPageIndexPage
));
606 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
607 src
, compressedSize
, buffer
, ppnum
);
615 // debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
616 // debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
620 // alloc new buffer page
621 bufferPage
= hibernate_page_list_grab(map
, &nextFree
);
623 if (copyPageIndex
> ((PAGE_SIZE
>> 2) - 3))
625 // alloc new copy list page
626 uint32_t pageListPage
= hibernate_page_list_grab(map
, &nextFree
);
629 copyPageList
[1] = pageListPage
;
631 copyPageListHead
= pageListPage
;
632 copyPageList
= (uint32_t *) (uintptr_t) ptoa_32(pageListPage
);
637 copyPageList
[copyPageIndex
++] = ppnum
;
638 copyPageList
[copyPageIndex
++] = bufferPage
;
639 copyPageList
[copyPageIndex
++] = compressedSize
;
640 copyPageList
[0] = copyPageIndex
;
642 dst
= (uint32_t *) (uintptr_t) ptoa_32(bufferPage
);
643 for (idx
= 0; idx
< ((compressedSize
+ 3) >> 2); idx
++)
646 src
+= ((compressedSize
+ 3) >> 2);
650 // -- copy back conflicts
652 copyPageList
= (uint32_t *)(uintptr_t) ptoa_32(copyPageListHead
);
655 for (copyPageIndex
= 2; copyPageIndex
< copyPageList
[0]; copyPageIndex
+= 3)
657 ppnum
= copyPageList
[copyPageIndex
+ 0];
658 src
= (uint32_t *) (uintptr_t) ptoa_32(copyPageList
[copyPageIndex
+ 1]);
659 compressedSize
= copyPageList
[copyPageIndex
+ 2];
661 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
662 src
, compressedSize
, buffer
, ppnum
);
665 copyPageList
= (uint32_t *) (uintptr_t) ptoa_32(copyPageList
[1]);
668 // -- image has been destroyed...
670 gIOHibernateCurrentHeader
->actualImage1Sum
= sum
;
671 gIOHibernateCurrentHeader
->actualUncompressedPages
= uncompressedPages
;
672 gIOHibernateCurrentHeader
->conflictCount
= conflictCount
;
673 gIOHibernateCurrentHeader
->nextFree
= nextFree
;
675 gIOHibernateState
= kIOHibernateStateWakingFromHibernate
;
679 typedef void (*ResetProc
)(void);
681 proc
= (ResetProc
) 0x100;
682 __asm__
volatile("ori 0, 0, 0" : : );
684 #elif defined(__i386__) || defined(__x86_64__)
685 typedef void (*ResetProc
)(void);
687 proc
= (ResetProc
) acpi_wake_prot_entry
;