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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
217 hibernate_sum_page(uint8_t *buf
, uint32_t ppnum
)
219 return (((uint32_t *)buf
)[((PAGE_SIZE
>> 2) - 1) & ppnum
]);
222 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
224 static hibernate_bitmap_t
*
225 hibernate_page_bitmap(hibernate_page_list_t
* list
, uint32_t page
)
228 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
230 for (bank
= 0; bank
< list
->bank_count
; bank
++)
232 if ((page
>= bitmap
->first_page
) && (page
<= bitmap
->last_page
))
234 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
236 if (bank
== list
->bank_count
)
243 hibernate_page_bitmap_pin(hibernate_page_list_t
* list
, uint32_t * pPage
)
245 uint32_t bank
, page
= *pPage
;
246 hibernate_bitmap_t
* bitmap
= &list
->bank_bitmap
[0];
248 for (bank
= 0; bank
< list
->bank_count
; bank
++)
250 if (page
<= bitmap
->first_page
)
252 *pPage
= bitmap
->first_page
;
255 if (page
<= bitmap
->last_page
)
257 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
259 if (bank
== list
->bank_count
)
266 hibernate_page_bitset(hibernate_page_list_t
* list
, boolean_t set
, uint32_t page
)
268 hibernate_bitmap_t
* bitmap
;
270 bitmap
= hibernate_page_bitmap(list
, page
);
273 page
-= bitmap
->first_page
;
275 bitmap
->bitmap
[page
>> 5] |= (0x80000000 >> (page
& 31));
276 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
278 bitmap
->bitmap
[page
>> 5] &= ~(0x80000000 >> (page
& 31));
279 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
284 hibernate_page_bittst(hibernate_page_list_t
* list
, uint32_t page
)
286 boolean_t result
= TRUE
;
287 hibernate_bitmap_t
* bitmap
;
289 bitmap
= hibernate_page_bitmap(list
, page
);
292 page
-= bitmap
->first_page
;
293 result
= (0 != (bitmap
->bitmap
[page
>> 5] & (0x80000000 >> (page
& 31))));
298 // count bits clear or set (set == TRUE) starting at page.
300 hibernate_page_bitmap_count(hibernate_bitmap_t
* bitmap
, uint32_t set
, uint32_t page
)
302 uint32_t index
, bit
, bits
;
307 index
= (page
- bitmap
->first_page
) >> 5;
308 bit
= (page
- bitmap
->first_page
) & 31;
310 bits
= bitmap
->bitmap
[index
];
313 bits
= (bits
<< bit
);
315 count
+= __builtin_clz(bits
);
319 while (++index
< bitmap
->bitmapwords
)
321 bits
= bitmap
->bitmap
[index
];
326 count
+= __builtin_clz(bits
);
337 hibernate_page_list_grab(hibernate_page_list_t
* list
, uint32_t * pNextFree
)
339 uint32_t nextFree
= *pNextFree
;
340 uint32_t nextFreeInBank
;
341 hibernate_bitmap_t
* bitmap
;
343 nextFreeInBank
= nextFree
+ 1;
344 while ((bitmap
= hibernate_page_bitmap_pin(list
, &nextFreeInBank
)))
346 nextFreeInBank
+= hibernate_page_bitmap_count(bitmap
, FALSE
, nextFreeInBank
);
347 if (nextFreeInBank
<= bitmap
->last_page
)
349 *pNextFree
= nextFreeInBank
;
356 debug_code(kIOHibernateRestoreCodeNoMemory
, nextFree
);
365 store_one_page(uint32_t procFlags
, uint32_t * src
, uint32_t compressedSize
,
366 uint32_t * buffer
, uint32_t ppnum
)
371 dst
= ptoa_64(ppnum
);
372 if (ppnum
< 0x00100000)
373 buffer
= (uint32_t *) (uintptr_t) dst
;
375 if (compressedSize
!= PAGE_SIZE
)
377 WKdm_decompress((WK_word
*) src
, (WK_word
*) buffer
, PAGE_SIZE
>> 2);
381 sum
= hibernate_sum_page((uint8_t *) src
, ppnum
);
383 if (((uint64_t) (uintptr_t) src
) == dst
)
386 hibernate_restore_phys_page((uint64_t) (uintptr_t) src
, dst
, PAGE_SIZE
, procFlags
);
391 // used only for small struct copies
393 bcopy_internal(const void *src
, void *dst
, uint32_t len
)
406 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
409 hibernate_kernel_entrypoint(IOHibernateImageHeader
* header
,
410 void * p2
, void * p3
, void * p4
)
415 uint32_t * pageIndexSource
;
416 hibernate_page_list_t
* map
;
420 uint32_t conflictCount
;
421 uint32_t compressedSize
;
422 uint32_t uncompressedPages
;
423 uint32_t copyPageListHead
;
424 uint32_t * copyPageList
;
425 uint32_t copyPageIndex
;
428 uint32_t lastImagePage
;
429 uint32_t lastMapPage
;
430 uint32_t lastPageIndexPage
;
432 C_ASSERT(sizeof(IOHibernateImageHeader
) == 512);
434 if ((kIOHibernateDebugRestoreLogs
& gIOHibernateDebugFlags
) && !debug_probe())
435 gIOHibernateDebugFlags
&= ~kIOHibernateDebugRestoreLogs
;
437 debug_code(kIOHibernateRestoreCodeImageStart
, (uintptr_t) header
);
439 bcopy_internal(header
,
440 gIOHibernateCurrentHeader
,
441 sizeof(IOHibernateImageHeader
));
445 count
= header
->graphicsInfoOffset
;
447 p2
= (void *)(((uintptr_t) header
) - count
);
451 gIOHibernateGraphicsInfo
,
452 sizeof(hibernate_graphics_t
));
454 gIOHibernateGraphicsInfo
->physicalAddress
= gIOHibernateGraphicsInfo
->depth
= 0;
458 count
= header
->cryptVarsOffset
;
460 p3
= (void *)(((uintptr_t) header
) - count
);
464 gIOHibernateCryptWakeVars
,
465 sizeof(hibernate_cryptwakevars_t
));
468 (((uintptr_t) &header
->fileExtentMap
[0])
469 + header
->fileExtentMapSize
470 + ptoa_32(header
->restore1PageCount
));
472 if (header
->previewSize
)
474 pageIndexSource
= src
;
475 map
= (hibernate_page_list_t
*)(((uintptr_t) pageIndexSource
) + header
->previewSize
);
476 src
= (uint32_t *) (((uintptr_t) pageIndexSource
) + header
->previewPageListSize
);
481 map
= (hibernate_page_list_t
*) src
;
482 src
= (uint32_t *) (((uintptr_t) map
) + header
->bitmapSize
);
485 lastPageIndexPage
= atop_32((uintptr_t) src
);
487 lastImagePage
= atop_32(((uintptr_t) header
) + header
->image1Size
);
489 lastMapPage
= atop_32(((uintptr_t) map
) + header
->bitmapSize
);
491 debug_code(kIOHibernateRestoreCodeImageEnd
, ptoa_64(lastImagePage
));
492 debug_code(kIOHibernateRestoreCodePageIndexStart
, (uintptr_t) pageIndexSource
);
493 debug_code(kIOHibernateRestoreCodePageIndexEnd
, ptoa_64(lastPageIndexPage
));
494 debug_code(kIOHibernateRestoreCodeMapStart
, (uintptr_t) map
);
495 debug_code(kIOHibernateRestoreCodeMapEnd
, ptoa_64(lastMapPage
));
497 // knock all the image pages to be used out of free map
498 for (ppnum
= atop_32((uintptr_t) header
); ppnum
<= lastImagePage
; ppnum
++)
500 hibernate_page_bitset(map
, FALSE
, ppnum
);
504 hibernate_page_list_grab(map
, &nextFree
);
505 buffer
= (uint32_t *) (uintptr_t) ptoa_32(hibernate_page_list_grab(map
, &nextFree
));
507 if (header
->memoryMapSize
&& (count
= header
->memoryMapOffset
))
509 p4
= (void *)(((uintptr_t) header
) - count
);
510 gIOHibernateWakeMap
= hibernate_page_list_grab(map
, &nextFree
);
511 gIOHibernateWakeMapSize
= header
->memoryMapSize
;
512 debug_code(kIOHibernateRestoreCodeWakeMapSize
, gIOHibernateWakeMapSize
);
513 if (gIOHibernateWakeMapSize
> PAGE_SIZE
)
515 bcopy_internal(p4
, (void *) (uintptr_t) ptoa_32(gIOHibernateWakeMap
), gIOHibernateWakeMapSize
);
518 gIOHibernateWakeMapSize
= 0;
520 sum
= gIOHibernateCurrentHeader
->actualRestore1Sum
;
521 gIOHibernateCurrentHeader
->diag
[0] = (uint32_t)(uintptr_t) header
;
522 gIOHibernateCurrentHeader
->diag
[1] = sum
;
524 uncompressedPages
= 0;
526 copyPageListHead
= 0;
528 copyPageIndex
= PAGE_SIZE
>> 2;
530 compressedSize
= PAGE_SIZE
;
536 ppnum
= pageIndexSource
[0];
537 count
= pageIndexSource
[1];
538 pageIndexSource
+= 2;
542 src
= (uint32_t *) (((uintptr_t) map
) + gIOHibernateCurrentHeader
->bitmapSize
);
557 for (page
= 0; page
< count
; page
++, ppnum
++)
562 if (!pageIndexSource
)
565 compressedSize
= kIOHibernateTagLength
& tag
;
568 conflicts
= (((ppnum
>= atop_32((uintptr_t) map
)) && (ppnum
<= lastMapPage
))
569 || ((ppnum
>= atop_32((uintptr_t) src
)) && (ppnum
<= lastImagePage
)));
572 conflicts
|= ((ppnum
>= atop_32((uintptr_t) pageIndexSource
)) && (ppnum
<= lastPageIndexPage
));
577 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
578 src
, compressedSize
, buffer
, ppnum
);
586 // debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
587 // debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
591 // alloc new buffer page
592 bufferPage
= hibernate_page_list_grab(map
, &nextFree
);
594 if (copyPageIndex
> ((PAGE_SIZE
>> 2) - 3))
596 // alloc new copy list page
597 uint32_t pageListPage
= hibernate_page_list_grab(map
, &nextFree
);
600 copyPageList
[1] = pageListPage
;
602 copyPageListHead
= pageListPage
;
603 copyPageList
= (uint32_t *) (uintptr_t) ptoa_32(pageListPage
);
608 copyPageList
[copyPageIndex
++] = ppnum
;
609 copyPageList
[copyPageIndex
++] = bufferPage
;
610 copyPageList
[copyPageIndex
++] = compressedSize
;
611 copyPageList
[0] = copyPageIndex
;
613 dst
= (uint32_t *) (uintptr_t) ptoa_32(bufferPage
);
614 for (idx
= 0; idx
< ((compressedSize
+ 3) >> 2); idx
++)
617 src
+= ((compressedSize
+ 3) >> 2);
621 // -- copy back conflicts
623 copyPageList
= (uint32_t *)(uintptr_t) ptoa_32(copyPageListHead
);
626 for (copyPageIndex
= 2; copyPageIndex
< copyPageList
[0]; copyPageIndex
+= 3)
628 ppnum
= copyPageList
[copyPageIndex
+ 0];
629 src
= (uint32_t *) (uintptr_t) ptoa_32(copyPageList
[copyPageIndex
+ 1]);
630 compressedSize
= copyPageList
[copyPageIndex
+ 2];
632 sum
+= store_one_page(gIOHibernateCurrentHeader
->processorFlags
,
633 src
, compressedSize
, buffer
, ppnum
);
636 copyPageList
= (uint32_t *) (uintptr_t) ptoa_32(copyPageList
[1]);
639 // -- image has been destroyed...
641 gIOHibernateCurrentHeader
->actualImage1Sum
= sum
;
642 gIOHibernateCurrentHeader
->actualUncompressedPages
= uncompressedPages
;
643 gIOHibernateCurrentHeader
->conflictCount
= conflictCount
;
644 gIOHibernateCurrentHeader
->nextFree
= nextFree
;
646 gIOHibernateState
= kIOHibernateStateWakingFromHibernate
;
650 typedef void (*ResetProc
)(void);
652 proc
= (ResetProc
) 0x100;
653 __asm__
volatile("ori 0, 0, 0" : : );
655 #elif defined(__i386__) || defined(__x86_64__)
656 typedef void (*ResetProc
)(void);
658 proc
= (ResetProc
) acpi_wake_prot_entry
;