]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOHibernateRestoreKernel.c
daf5d2804b2405acee3cda41ab3f9c7b48a6a06a
[apple/xnu.git] / iokit / Kernel / IOHibernateRestoreKernel.c
1 /*
2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <stdint.h>
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 <libkern/libkern.h>
36
37 #include <vm/WKdm_new.h>
38 #include "IOHibernateInternal.h"
39
40 #include <machine/pal_hibernate.h>
41
42 /*
43 This code is linked into the kernel but part of the "__HIB" section, which means
44 its used by code running in the special context of restoring the kernel text and data
45 from the hibernation image read by the booter. hibernate_kernel_entrypoint() and everything
46 it calls or references needs to be careful to only touch memory also in the "__HIB" section.
47 */
48
49 uint32_t gIOHibernateState;
50
51 uint32_t gIOHibernateDebugFlags;
52
53 static IOHibernateImageHeader _hibernateHeader;
54 IOHibernateImageHeader * gIOHibernateCurrentHeader = &_hibernateHeader;
55
56 ppnum_t gIOHibernateHandoffPages[64];
57 uint32_t gIOHibernateHandoffPageCount = sizeof(gIOHibernateHandoffPages)
58 / sizeof(gIOHibernateHandoffPages[0]);
59
60 #if CONFIG_DEBUG
61 void hibprintf(const char *fmt, ...);
62 #else
63 #define hibprintf(x...)
64 #endif
65
66
67 #if CONFIG_SLEEP
68 #if defined(__i386__) || defined(__x86_64__)
69 extern void acpi_wake_prot_entry(void);
70 #endif
71 #endif
72
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
74
75 #if defined(__i386__) || defined(__x86_64__)
76
77 #define rdtsc(lo,hi) \
78 __asm__ volatile("lfence; rdtsc; lfence" : "=a" (lo), "=d" (hi))
79
80 static inline uint64_t rdtsc64(void)
81 {
82 uint64_t lo, hi;
83 rdtsc(lo, hi);
84 return ((hi) << 32) | (lo);
85 }
86
87 #else
88
89 static inline uint64_t rdtsc64(void)
90 {
91 return (0);
92 }
93
94 #endif /* defined(__i386__) || defined(__x86_64__) */
95
96 #if defined(__i386__) || defined(__x86_64__)
97
98 #define DBGLOG 1
99
100 #include <architecture/i386/pio.h>
101
102 /* standard port addresses */
103 enum {
104 COM1_PORT_ADDR = 0x3f8,
105 COM2_PORT_ADDR = 0x2f8
106 };
107
108 /* UART register offsets */
109 enum {
110 UART_RBR = 0, /* receive buffer Register (R) */
111 UART_THR = 0, /* transmit holding register (W) */
112 UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */
113 UART_IER = 1, /* interrupt enable register */
114 UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */
115 UART_IIR = 2, /* interrupt ident register (R) */
116 UART_FCR = 2, /* fifo control register (W) */
117 UART_LCR = 3, /* line control register */
118 UART_MCR = 4, /* modem control register */
119 UART_LSR = 5, /* line status register */
120 UART_MSR = 6, /* modem status register */
121 UART_SCR = 7 /* scratch register */
122 };
123
124 enum {
125 UART_LCR_8BITS = 0x03,
126 UART_LCR_DLAB = 0x80
127 };
128
129 enum {
130 UART_MCR_DTR = 0x01,
131 UART_MCR_RTS = 0x02,
132 UART_MCR_OUT1 = 0x04,
133 UART_MCR_OUT2 = 0x08,
134 UART_MCR_LOOP = 0x10
135 };
136
137 enum {
138 UART_LSR_DR = 0x01,
139 UART_LSR_OE = 0x02,
140 UART_LSR_PE = 0x04,
141 UART_LSR_FE = 0x08,
142 UART_LSR_THRE = 0x20
143 };
144
145 static void uart_putc(char c)
146 {
147 while (!(inb(COM1_PORT_ADDR + UART_LSR) & UART_LSR_THRE))
148 {}
149 outb(COM1_PORT_ADDR + UART_THR, c);
150 }
151
152 static int debug_probe( void )
153 {
154 /* Verify that the Scratch Register is accessible */
155 outb(COM1_PORT_ADDR + UART_SCR, 0x5a);
156 if (inb(COM1_PORT_ADDR + UART_SCR) != 0x5a) return false;
157 outb(COM1_PORT_ADDR + UART_SCR, 0xa5);
158 if (inb(COM1_PORT_ADDR + UART_SCR) != 0xa5) return false;
159 uart_putc('\n');
160 return true;
161 }
162
163 static void uart_puthex(uint64_t num)
164 {
165 int bit;
166 char c;
167 bool leading = true;
168
169 for (bit = 60; bit >= 0; bit -= 4)
170 {
171 c = 0xf & (num >> bit);
172 if (c)
173 leading = false;
174 else if (leading && bit)
175 continue;
176 if (c <= 9)
177 c += '0';
178 else
179 c+= 'a' - 10;
180 uart_putc(c);
181 }
182 }
183
184 static void debug_code(uint32_t code, uint64_t value)
185 {
186 int bit;
187 char c;
188
189 if (!(kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags))
190 return;
191
192 for (bit = 24; bit >= 0; bit -= 8)
193 {
194 c = 0xFF & (code >> bit);
195 if (c)
196 uart_putc(c);
197 }
198 uart_putc('=');
199 uart_puthex(value);
200 uart_putc('\n');
201 uart_putc('\r');
202 }
203
204 #endif /* defined(__i386__) || defined(__x86_64__) */
205
206 #if !defined(DBGLOG)
207 #define debug_probe() (false)
208 #define debug_code(c, v) {}
209 #endif
210
211 enum
212 {
213 kIOHibernateRestoreCodeImageStart = 'imgS',
214 kIOHibernateRestoreCodeImageEnd = 'imgE',
215 kIOHibernateRestoreCodePageIndexStart = 'pgiS',
216 kIOHibernateRestoreCodePageIndexEnd = 'pgiE',
217 kIOHibernateRestoreCodeMapStart = 'mapS',
218 kIOHibernateRestoreCodeMapEnd = 'mapE',
219 kIOHibernateRestoreCodeWakeMapSize = 'wkms',
220 kIOHibernateRestoreCodeConflictPage = 'cfpg',
221 kIOHibernateRestoreCodeConflictSource = 'cfsr',
222 kIOHibernateRestoreCodeNoMemory = 'nomm',
223 kIOHibernateRestoreCodeTag = 'tag ',
224 kIOHibernateRestoreCodeSignature = 'sign',
225 kIOHibernateRestoreCodeMapVirt = 'mapV',
226 kIOHibernateRestoreCodeHandoffPages = 'hand',
227 kIOHibernateRestoreCodeHandoffCount = 'hndc',
228 };
229
230 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
231
232
233 static void fatal(void)
234 {
235 #if defined(__i386__) || defined(__x86_64__)
236 outb(0xcf9, 6);
237 #else
238 while (true) {}
239 #endif
240 }
241
242 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
243
244 uint32_t
245 hibernate_sum_page(uint8_t *buf, uint32_t ppnum)
246 {
247 return (((uint32_t *)buf)[((PAGE_SIZE >> 2) - 1) & ppnum]);
248 }
249
250 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
251
252 static hibernate_bitmap_t *
253 hibernate_page_bitmap(hibernate_page_list_t * list, uint32_t page)
254 {
255 uint32_t bank;
256 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
257
258 for (bank = 0; bank < list->bank_count; bank++)
259 {
260 if ((page >= bitmap->first_page) && (page <= bitmap->last_page))
261 break;
262 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
263 }
264 if (bank == list->bank_count)
265 bitmap = NULL;
266
267 return (bitmap);
268 }
269
270 hibernate_bitmap_t *
271 hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * pPage)
272 {
273 uint32_t bank, page = *pPage;
274 hibernate_bitmap_t * bitmap = &list->bank_bitmap[0];
275
276 for (bank = 0; bank < list->bank_count; bank++)
277 {
278 if (page <= bitmap->first_page)
279 {
280 *pPage = bitmap->first_page;
281 break;
282 }
283 if (page <= bitmap->last_page)
284 break;
285 bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords];
286 }
287 if (bank == list->bank_count)
288 bitmap = NULL;
289
290 return (bitmap);
291 }
292
293 void
294 hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page)
295 {
296 hibernate_bitmap_t * bitmap;
297
298 bitmap = hibernate_page_bitmap(list, page);
299 if (bitmap)
300 {
301 page -= bitmap->first_page;
302 if (set)
303 bitmap->bitmap[page >> 5] |= (0x80000000 >> (page & 31));
304 //setbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
305 else
306 bitmap->bitmap[page >> 5] &= ~(0x80000000 >> (page & 31));
307 //clrbit(page - bitmap->first_page, (int *) &bitmap->bitmap[0]);
308 }
309 }
310
311 boolean_t
312 hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page)
313 {
314 boolean_t result = TRUE;
315 hibernate_bitmap_t * bitmap;
316
317 bitmap = hibernate_page_bitmap(list, page);
318 if (bitmap)
319 {
320 page -= bitmap->first_page;
321 result = (0 != (bitmap->bitmap[page >> 5] & (0x80000000 >> (page & 31))));
322 }
323 return (result);
324 }
325
326 // count bits clear or set (set == TRUE) starting at page.
327 uint32_t
328 hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page)
329 {
330 uint32_t index, bit, bits;
331 uint32_t count;
332
333 count = 0;
334
335 index = (page - bitmap->first_page) >> 5;
336 bit = (page - bitmap->first_page) & 31;
337
338 bits = bitmap->bitmap[index];
339 if (set)
340 bits = ~bits;
341 bits = (bits << bit);
342 if (bits)
343 count += __builtin_clz(bits);
344 else
345 {
346 count += 32 - bit;
347 while (++index < bitmap->bitmapwords)
348 {
349 bits = bitmap->bitmap[index];
350 if (set)
351 bits = ~bits;
352 if (bits)
353 {
354 count += __builtin_clz(bits);
355 break;
356 }
357 count += 32;
358 }
359 }
360
361 if ((page + count) > (bitmap->last_page + 1)) count = (bitmap->last_page + 1) - page;
362
363 return (count);
364 }
365
366 static ppnum_t
367 hibernate_page_list_grab(hibernate_page_list_t * list, uint32_t * pNextFree)
368 {
369 uint32_t nextFree = *pNextFree;
370 uint32_t nextFreeInBank;
371 hibernate_bitmap_t * bitmap;
372
373 nextFreeInBank = nextFree + 1;
374 while ((bitmap = hibernate_page_bitmap_pin(list, &nextFreeInBank)))
375 {
376 nextFreeInBank += hibernate_page_bitmap_count(bitmap, FALSE, nextFreeInBank);
377 if (nextFreeInBank <= bitmap->last_page)
378 {
379 *pNextFree = nextFreeInBank;
380 break;
381 }
382 }
383
384 if (!bitmap)
385 {
386 debug_code(kIOHibernateRestoreCodeNoMemory, nextFree);
387 fatal();
388 nextFree = 0;
389 }
390
391 return (nextFree);
392 }
393
394 static uint32_t
395 store_one_page(uint32_t procFlags, uint32_t * src, uint32_t compressedSize,
396 uint32_t * buffer, uint32_t ppnum)
397 {
398 uint64_t dst = ptoa_64(ppnum);
399 uint8_t scratch[WKdm_SCRATCH_BUF_SIZE] __attribute__ ((aligned (16)));
400
401 if (compressedSize != PAGE_SIZE)
402 {
403 dst = pal_hib_map(DEST_COPY_AREA, dst);
404 if (compressedSize) WKdm_decompress_new((WK_word*) src, (WK_word*)(uintptr_t)dst, (WK_word*) &scratch[0], PAGE_SIZE);
405 else bzero((void *) dst, PAGE_SIZE);
406 }
407 else
408 {
409 dst = hibernate_restore_phys_page((uint64_t) (uintptr_t) src, dst, PAGE_SIZE, procFlags);
410 }
411
412 return hibernate_sum_page((uint8_t *)(uintptr_t)dst, ppnum);
413 }
414
415 #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1]
416
417 long
418 hibernate_kernel_entrypoint(uint32_t p1,
419 uint32_t p2, uint32_t p3, uint32_t p4)
420 {
421 uint64_t headerPhys;
422 uint64_t mapPhys;
423 uint64_t srcPhys;
424 uint64_t imageReadPhys;
425 uint64_t pageIndexPhys;
426 uint32_t * pageIndexSource;
427 hibernate_page_list_t * map;
428 uint32_t stage;
429 uint32_t count;
430 uint32_t ppnum;
431 uint32_t page;
432 uint32_t conflictCount;
433 uint32_t compressedSize;
434 uint32_t uncompressedPages;
435 uint32_t copyPageListHeadPage;
436 uint32_t pageListPage;
437 uint32_t * copyPageList;
438 uint32_t * src;
439 uint32_t copyPageIndex;
440 uint32_t sum;
441 uint32_t pageSum;
442 uint32_t nextFree;
443 uint32_t lastImagePage;
444 uint32_t lastMapPage;
445 uint32_t lastPageIndexPage;
446 uint32_t handoffPages;
447 uint32_t handoffPageCount;
448
449 uint64_t timeStart;
450 timeStart = rdtsc64();
451
452 C_ASSERT(sizeof(IOHibernateImageHeader) == 512);
453
454 headerPhys = ptoa_64(p1);
455
456 if ((kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags) && !debug_probe())
457 gIOHibernateDebugFlags &= ~kIOHibernateDebugRestoreLogs;
458
459 debug_code(kIOHibernateRestoreCodeImageStart, headerPhys);
460
461 memcpy(gIOHibernateCurrentHeader,
462 (void *) pal_hib_map(IMAGE_AREA, headerPhys),
463 sizeof(IOHibernateImageHeader));
464
465 debug_code(kIOHibernateRestoreCodeSignature, gIOHibernateCurrentHeader->signature);
466
467 mapPhys = headerPhys
468 + (offsetof(IOHibernateImageHeader, fileExtentMap)
469 + gIOHibernateCurrentHeader->fileExtentMapSize
470 + ptoa_32(gIOHibernateCurrentHeader->restore1PageCount)
471 + gIOHibernateCurrentHeader->previewSize);
472
473 map = (hibernate_page_list_t *) pal_hib_map(BITMAP_AREA, mapPhys);
474
475 lastImagePage = atop_64(headerPhys + gIOHibernateCurrentHeader->image1Size);
476 lastMapPage = atop_64(mapPhys + gIOHibernateCurrentHeader->bitmapSize);
477
478 handoffPages = gIOHibernateCurrentHeader->handoffPages;
479 handoffPageCount = gIOHibernateCurrentHeader->handoffPageCount;
480
481 debug_code(kIOHibernateRestoreCodeImageEnd, ptoa_64(lastImagePage));
482 debug_code(kIOHibernateRestoreCodeMapStart, mapPhys);
483 debug_code(kIOHibernateRestoreCodeMapEnd, ptoa_64(lastMapPage));
484
485 debug_code(kIOHibernateRestoreCodeMapVirt, (uintptr_t) map);
486 debug_code(kIOHibernateRestoreCodeHandoffPages, ptoa_64(handoffPages));
487 debug_code(kIOHibernateRestoreCodeHandoffCount, handoffPageCount);
488
489 // knock all the image pages to be used out of free map
490 for (ppnum = atop_64(headerPhys); ppnum <= lastImagePage; ppnum++)
491 {
492 hibernate_page_bitset(map, FALSE, ppnum);
493 }
494 // knock all the handoff pages to be used out of free map
495 for (ppnum = handoffPages; ppnum < (handoffPages + handoffPageCount); ppnum++)
496 {
497 hibernate_page_bitset(map, FALSE, ppnum);
498 }
499
500 nextFree = 0;
501 hibernate_page_list_grab(map, &nextFree);
502
503 sum = gIOHibernateCurrentHeader->actualRestore1Sum;
504 gIOHibernateCurrentHeader->diag[0] = atop_64(headerPhys);
505 gIOHibernateCurrentHeader->diag[1] = sum;
506 gIOHibernateCurrentHeader->trampolineTime = 0;
507
508 uncompressedPages = 0;
509 conflictCount = 0;
510 copyPageListHeadPage = 0;
511 copyPageList = 0;
512 copyPageIndex = PAGE_SIZE >> 2;
513
514 compressedSize = PAGE_SIZE;
515 stage = 2;
516 count = 0;
517 srcPhys = 0;
518
519 if (gIOHibernateCurrentHeader->previewSize)
520 {
521 pageIndexPhys = headerPhys
522 + (offsetof(IOHibernateImageHeader, fileExtentMap)
523 + gIOHibernateCurrentHeader->fileExtentMapSize
524 + ptoa_32(gIOHibernateCurrentHeader->restore1PageCount));
525 imageReadPhys = (pageIndexPhys + gIOHibernateCurrentHeader->previewPageListSize);
526 lastPageIndexPage = atop_64(imageReadPhys);
527 pageIndexSource = (uint32_t *) pal_hib_map(IMAGE2_AREA, pageIndexPhys);
528 }
529 else
530 {
531 pageIndexPhys = 0;
532 lastPageIndexPage = 0;
533 imageReadPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
534 }
535
536 debug_code(kIOHibernateRestoreCodePageIndexStart, pageIndexPhys);
537 debug_code(kIOHibernateRestoreCodePageIndexEnd, ptoa_64(lastPageIndexPage));
538
539 while (1)
540 {
541 switch (stage)
542 {
543 case 2:
544 // copy handoff data
545 count = srcPhys ? 0 : handoffPageCount;
546 if (!count)
547 break;
548 if (count > gIOHibernateHandoffPageCount) count = gIOHibernateHandoffPageCount;
549 srcPhys = ptoa_64(handoffPages);
550 break;
551
552 case 1:
553 // copy pageIndexSource pages == preview image data
554 if (!srcPhys)
555 {
556 if (!pageIndexPhys) break;
557 srcPhys = imageReadPhys;
558 }
559 ppnum = pageIndexSource[0];
560 count = pageIndexSource[1];
561 pageIndexSource += 2;
562 pageIndexPhys += 2 * sizeof(pageIndexSource[0]);
563 imageReadPhys = srcPhys;
564 break;
565
566 case 0:
567 // copy pages
568 if (!srcPhys) srcPhys = (mapPhys + gIOHibernateCurrentHeader->bitmapSize);
569 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
570 ppnum = src[0];
571 count = src[1];
572 srcPhys += 2 * sizeof(*src);
573 imageReadPhys = srcPhys;
574 break;
575 }
576
577
578 if (!count)
579 {
580 if (!stage)
581 break;
582 stage--;
583 srcPhys = 0;
584 continue;
585 }
586
587 for (page = 0; page < count; page++, ppnum++)
588 {
589 uint32_t tag;
590 int conflicts;
591
592 src = (uint32_t *) pal_hib_map(IMAGE_AREA, srcPhys);
593
594 if (2 == stage) ppnum = gIOHibernateHandoffPages[page];
595 else if (!stage)
596 {
597 tag = *src++;
598 // debug_code(kIOHibernateRestoreCodeTag, (uintptr_t) tag);
599 srcPhys += sizeof(*src);
600 compressedSize = kIOHibernateTagLength & tag;
601 }
602
603 conflicts = (ppnum >= atop_64(mapPhys)) && (ppnum <= lastMapPage);
604
605 conflicts |= ((ppnum >= atop_64(imageReadPhys)) && (ppnum <= lastImagePage));
606
607 if (stage >= 2)
608 conflicts |= ((ppnum >= atop_64(srcPhys)) && (ppnum <= (handoffPages + handoffPageCount - 1)));
609
610 if (stage >= 1)
611 conflicts |= ((ppnum >= atop_64(pageIndexPhys)) && (ppnum <= lastPageIndexPage));
612
613 if (!conflicts)
614 {
615 pageSum = store_one_page(gIOHibernateCurrentHeader->processorFlags,
616 src, compressedSize, 0, ppnum);
617 if (stage != 2)
618 sum += pageSum;
619 uncompressedPages++;
620 }
621 else
622 {
623 uint32_t bufferPage = 0;
624 uint32_t * dst;
625
626 // debug_code(kIOHibernateRestoreCodeConflictPage, ppnum);
627 // debug_code(kIOHibernateRestoreCodeConflictSource, (uintptr_t) src);
628 conflictCount++;
629 if (compressedSize)
630 {
631 // alloc new buffer page
632 bufferPage = hibernate_page_list_grab(map, &nextFree);
633 dst = (uint32_t *)pal_hib_map(DEST_COPY_AREA, ptoa_64(bufferPage));
634 memcpy(dst, src, compressedSize);
635 }
636 if (copyPageIndex > ((PAGE_SIZE >> 2) - 3))
637 {
638 // alloc new copy list page
639 pageListPage = hibernate_page_list_grab(map, &nextFree);
640 // link to current
641 if (copyPageList) {
642 copyPageList[1] = pageListPage;
643 } else {
644 copyPageListHeadPage = pageListPage;
645 }
646 copyPageList = (uint32_t *)pal_hib_map(SRC_COPY_AREA,
647 ptoa_64(pageListPage));
648 copyPageList[1] = 0;
649 copyPageIndex = 2;
650 }
651 copyPageList[copyPageIndex++] = ppnum;
652 copyPageList[copyPageIndex++] = bufferPage;
653 copyPageList[copyPageIndex++] = (compressedSize | (stage << 24));
654 copyPageList[0] = copyPageIndex;
655 }
656 srcPhys += ((compressedSize + 3) & ~3);
657 src += ((compressedSize + 3) >> 2);
658 }
659 }
660
661 /* src points to the last page restored, so we need to skip over that */
662 hibernateRestorePALState(src);
663
664 // -- copy back conflicts
665
666 pageListPage = copyPageListHeadPage;
667 while (pageListPage)
668 {
669 copyPageList = (uint32_t *)pal_hib_map(COPY_PAGE_AREA, ptoa_64(pageListPage));
670 for (copyPageIndex = 2; copyPageIndex < copyPageList[0]; copyPageIndex += 3)
671 {
672 ppnum = copyPageList[copyPageIndex + 0];
673 srcPhys = ptoa_64(copyPageList[copyPageIndex + 1]);
674 src = (uint32_t *) pal_hib_map(SRC_COPY_AREA, srcPhys);
675 compressedSize = copyPageList[copyPageIndex + 2];
676 stage = compressedSize >> 24;
677 compressedSize &= 0x1FFF;
678 pageSum = store_one_page(gIOHibernateCurrentHeader->processorFlags,
679 src, compressedSize, 0, ppnum);
680 if (stage != 2)
681 sum += pageSum;
682 uncompressedPages++;
683 }
684 pageListPage = copyPageList[1];
685 }
686
687 pal_hib_patchup();
688
689 // -- image has been destroyed...
690
691 gIOHibernateCurrentHeader->actualImage1Sum = sum;
692 gIOHibernateCurrentHeader->actualUncompressedPages = uncompressedPages;
693 gIOHibernateCurrentHeader->conflictCount = conflictCount;
694 gIOHibernateCurrentHeader->nextFree = nextFree;
695
696 gIOHibernateState = kIOHibernateStateWakingFromHibernate;
697
698 gIOHibernateCurrentHeader->trampolineTime = (((rdtsc64() - timeStart)) >> 8);
699
700 #if CONFIG_SLEEP
701 #if defined(__i386__) || defined(__x86_64__)
702 typedef void (*ResetProc)(void);
703 ResetProc proc;
704 proc = HIB_ENTRYPOINT;
705 // flush caches
706 __asm__("wbinvd");
707 proc();
708 #else
709 // implement me
710 #endif
711 #endif
712
713 return -1;
714 }
715
716 #if CONFIG_DEBUG
717 /* standalone printf implementation */
718 /*-
719 * Copyright (c) 1986, 1988, 1991, 1993
720 * The Regents of the University of California. All rights reserved.
721 * (c) UNIX System Laboratories, Inc.
722 * All or some portions of this file are derived from material licensed
723 * to the University of California by American Telephone and Telegraph
724 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
725 * the permission of UNIX System Laboratories, Inc.
726 *
727 * Redistribution and use in source and binary forms, with or without
728 * modification, are permitted provided that the following conditions
729 * are met:
730 * 1. Redistributions of source code must retain the above copyright
731 * notice, this list of conditions and the following disclaimer.
732 * 2. Redistributions in binary form must reproduce the above copyright
733 * notice, this list of conditions and the following disclaimer in the
734 * documentation and/or other materials provided with the distribution.
735 * 4. Neither the name of the University nor the names of its contributors
736 * may be used to endorse or promote products derived from this software
737 * without specific prior written permission.
738 *
739 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
740 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
741 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
742 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
743 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
744 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
745 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
746 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
747 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
748 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
749 * SUCH DAMAGE.
750 *
751 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
752 */
753
754 typedef long ptrdiff_t;
755 char const hibhex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
756 #define hibhex2ascii(hex) (hibhex2ascii_data[hex])
757 #define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
758 static size_t
759 hibstrlen(const char *s)
760 {
761 size_t l = 0;
762 while (*s++)
763 l++;
764 return l;
765 }
766
767 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
768 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
769
770 /*
771 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
772 * order; return an optional length and a pointer to the last character
773 * written in the buffer (i.e., the first character of the string).
774 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
775 */
776 static char *
777 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
778 {
779 char *p, c;
780
781 /* Truncate so we don't call umoddi3, which isn't in __HIB */
782 #if !defined(__LP64__)
783 uint32_t num2 = (uint32_t) num;
784 #else
785 uintmax_t num2 = num;
786 #endif
787
788 p = nbuf;
789 *p = '\0';
790 do {
791 c = hibhex2ascii(num2 % base);
792 *++p = upper ? toupper(c) : c;
793 } while (num2 /= base);
794 if (lenp)
795 *lenp = (int)(p - nbuf);
796 return (p);
797 }
798
799 /*
800 * Scaled down version of printf(3).
801 *
802 * Two additional formats:
803 *
804 * The format %b is supported to decode error registers.
805 * Its usage is:
806 *
807 * printf("reg=%b\n", regval, "*");
808 *
809 * where is the output base expressed as a control character, e.g.
810 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
811 * the first of which gives the bit number to be inspected (origin 1), and
812 * the next characters (up to a control character, i.e. a character <= 32),
813 * give the name of the register. Thus:
814 *
815 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
816 *
817 * would produce output:
818 *
819 * reg=3
820 *
821 * XXX: %D -- Hexdump, takes pointer and separator string:
822 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
823 * ("%*D", len, ptr, " " -> XX XX XX XX ...
824 */
825 static int
826 hibkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
827 {
828 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
829 char nbuf[MAXNBUF];
830 char *d;
831 const char *p, *percent, *q;
832 u_char *up;
833 int ch, n;
834 uintmax_t num;
835 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
836 int cflag, hflag, jflag, tflag, zflag;
837 int dwidth, upper;
838 char padc;
839 int stop = 0, retval = 0;
840
841 num = 0;
842 if (!func)
843 d = (char *) arg;
844 else
845 d = NULL;
846
847 if (fmt == NULL)
848 fmt = "(fmt null)\n";
849
850 if (radix < 2 || radix > 36)
851 radix = 10;
852
853 for (;;) {
854 padc = ' ';
855 width = 0;
856 while ((ch = (u_char)*fmt++) != '%' || stop) {
857 if (ch == '\0')
858 return (retval);
859 PCHAR(ch);
860 }
861 percent = fmt - 1;
862 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
863 sign = 0; dot = 0; dwidth = 0; upper = 0;
864 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
865 reswitch: switch (ch = (u_char)*fmt++) {
866 case '.':
867 dot = 1;
868 goto reswitch;
869 case '#':
870 sharpflag = 1;
871 goto reswitch;
872 case '+':
873 sign = 1;
874 goto reswitch;
875 case '-':
876 ladjust = 1;
877 goto reswitch;
878 case '%':
879 PCHAR(ch);
880 break;
881 case '*':
882 if (!dot) {
883 width = va_arg(ap, int);
884 if (width < 0) {
885 ladjust = !ladjust;
886 width = -width;
887 }
888 } else {
889 dwidth = va_arg(ap, int);
890 }
891 goto reswitch;
892 case '0':
893 if (!dot) {
894 padc = '0';
895 goto reswitch;
896 }
897 case '1': case '2': case '3': case '4':
898 case '5': case '6': case '7': case '8': case '9':
899 for (n = 0;; ++fmt) {
900 n = n * 10 + ch - '0';
901 ch = *fmt;
902 if (ch < '0' || ch > '9')
903 break;
904 }
905 if (dot)
906 dwidth = n;
907 else
908 width = n;
909 goto reswitch;
910 case 'b':
911 num = (u_int)va_arg(ap, int);
912 p = va_arg(ap, char *);
913 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
914 PCHAR(*q--);
915
916 if (num == 0)
917 break;
918
919 for (tmp = 0; *p;) {
920 n = *p++;
921 if (num & (1 << (n - 1))) {
922 PCHAR(tmp ? ',' : '<');
923 for (; (n = *p) > ' '; ++p)
924 PCHAR(n);
925 tmp = 1;
926 } else
927 for (; *p > ' '; ++p)
928 continue;
929 }
930 if (tmp)
931 PCHAR('>');
932 break;
933 case 'c':
934 PCHAR(va_arg(ap, int));
935 break;
936 case 'D':
937 up = va_arg(ap, u_char *);
938 p = va_arg(ap, char *);
939 if (!width)
940 width = 16;
941 while(width--) {
942 PCHAR(hibhex2ascii(*up >> 4));
943 PCHAR(hibhex2ascii(*up & 0x0f));
944 up++;
945 if (width)
946 for (q=p;*q;q++)
947 PCHAR(*q);
948 }
949 break;
950 case 'd':
951 case 'i':
952 base = 10;
953 sign = 1;
954 goto handle_sign;
955 case 'h':
956 if (hflag) {
957 hflag = 0;
958 cflag = 1;
959 } else
960 hflag = 1;
961 goto reswitch;
962 case 'j':
963 jflag = 1;
964 goto reswitch;
965 case 'l':
966 if (lflag) {
967 lflag = 0;
968 qflag = 1;
969 } else
970 lflag = 1;
971 goto reswitch;
972 case 'n':
973 if (jflag)
974 *(va_arg(ap, intmax_t *)) = retval;
975 else if (qflag)
976 *(va_arg(ap, quad_t *)) = retval;
977 else if (lflag)
978 *(va_arg(ap, long *)) = retval;
979 else if (zflag)
980 *(va_arg(ap, size_t *)) = retval;
981 else if (hflag)
982 *(va_arg(ap, short *)) = retval;
983 else if (cflag)
984 *(va_arg(ap, char *)) = retval;
985 else
986 *(va_arg(ap, int *)) = retval;
987 break;
988 case 'o':
989 base = 8;
990 goto handle_nosign;
991 case 'p':
992 base = 16;
993 sharpflag = (width == 0);
994 sign = 0;
995 num = (uintptr_t)va_arg(ap, void *);
996 goto number;
997 case 'q':
998 qflag = 1;
999 goto reswitch;
1000 case 'r':
1001 base = radix;
1002 if (sign)
1003 goto handle_sign;
1004 goto handle_nosign;
1005 case 's':
1006 p = va_arg(ap, char *);
1007 if (p == NULL)
1008 p = "(null)";
1009 if (!dot)
1010 n = (typeof(n))hibstrlen (p);
1011 else
1012 for (n = 0; n < dwidth && p[n]; n++)
1013 continue;
1014
1015 width -= n;
1016
1017 if (!ladjust && width > 0)
1018 while (width--)
1019 PCHAR(padc);
1020 while (n--)
1021 PCHAR(*p++);
1022 if (ladjust && width > 0)
1023 while (width--)
1024 PCHAR(padc);
1025 break;
1026 case 't':
1027 tflag = 1;
1028 goto reswitch;
1029 case 'u':
1030 base = 10;
1031 goto handle_nosign;
1032 case 'X':
1033 upper = 1;
1034 case 'x':
1035 base = 16;
1036 goto handle_nosign;
1037 case 'y':
1038 base = 16;
1039 sign = 1;
1040 goto handle_sign;
1041 case 'z':
1042 zflag = 1;
1043 goto reswitch;
1044 handle_nosign:
1045 sign = 0;
1046 if (jflag)
1047 num = va_arg(ap, uintmax_t);
1048 else if (qflag)
1049 num = va_arg(ap, u_quad_t);
1050 else if (tflag)
1051 num = va_arg(ap, ptrdiff_t);
1052 else if (lflag)
1053 num = va_arg(ap, u_long);
1054 else if (zflag)
1055 num = va_arg(ap, size_t);
1056 else if (hflag)
1057 num = (u_short)va_arg(ap, int);
1058 else if (cflag)
1059 num = (u_char)va_arg(ap, int);
1060 else
1061 num = va_arg(ap, u_int);
1062 goto number;
1063 handle_sign:
1064 if (jflag)
1065 num = va_arg(ap, intmax_t);
1066 else if (qflag)
1067 num = va_arg(ap, quad_t);
1068 else if (tflag)
1069 num = va_arg(ap, ptrdiff_t);
1070 else if (lflag)
1071 num = va_arg(ap, long);
1072 else if (zflag)
1073 num = va_arg(ap, ssize_t);
1074 else if (hflag)
1075 num = (short)va_arg(ap, int);
1076 else if (cflag)
1077 num = (char)va_arg(ap, int);
1078 else
1079 num = va_arg(ap, int);
1080 number:
1081 if (sign && (intmax_t)num < 0) {
1082 neg = 1;
1083 num = -(intmax_t)num;
1084 }
1085 p = ksprintn(nbuf, num, base, &tmp, upper);
1086 if (sharpflag && num != 0) {
1087 if (base == 8)
1088 tmp++;
1089 else if (base == 16)
1090 tmp += 2;
1091 }
1092 if (neg)
1093 tmp++;
1094
1095 if (!ladjust && padc != '0' && width
1096 && (width -= tmp) > 0)
1097 while (width--)
1098 PCHAR(padc);
1099 if (neg)
1100 PCHAR('-');
1101 if (sharpflag && num != 0) {
1102 if (base == 8) {
1103 PCHAR('0');
1104 } else if (base == 16) {
1105 PCHAR('0');
1106 PCHAR('x');
1107 }
1108 }
1109 if (!ladjust && width && (width -= tmp) > 0)
1110 while (width--)
1111 PCHAR(padc);
1112
1113 while (*p)
1114 PCHAR(*p--);
1115
1116 if (ladjust && width && (width -= tmp) > 0)
1117 while (width--)
1118 PCHAR(padc);
1119
1120 break;
1121 default:
1122 while (percent < fmt)
1123 PCHAR(*percent++);
1124 /*
1125 * Since we ignore an formatting argument it is no
1126 * longer safe to obey the remaining formatting
1127 * arguments as the arguments will no longer match
1128 * the format specs.
1129 */
1130 stop = 1;
1131 break;
1132 }
1133 }
1134 #undef PCHAR
1135 }
1136
1137
1138 static void
1139 putchar(int c, void *arg)
1140 {
1141 (void)arg;
1142 uart_putc(c);
1143 }
1144
1145 void
1146 hibprintf(const char *fmt, ...)
1147 {
1148 /* http://www.pagetable.com/?p=298 */
1149 va_list ap;
1150
1151 va_start(ap, fmt);
1152 hibkvprintf(fmt, putchar, NULL, 10, ap);
1153 va_end(ap);
1154 }
1155 #endif /* CONFIG_DEBUG */
1156