Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/i386/boot2/resume.c

1/*
2 * resume.c
3 *
4 *
5 * Created by mackerintel on 1/22/09.
6 * Copyright 2009 mackerintel. All rights reserved.
7 *
8 */
9
10#include "saio_internal.h"
11#include "libsa.h"
12#include "IOHibernatePrivate.h"
13#include "memory.h"
14#include "bootstruct.h"
15#include "boot.h"
16#include "pci.h"
17
18extern int previewTotalSectors;
19extern int previewLoadedSectors;
20extern uint8_t *previewSaveunder;
21
22static unsigned long
23getmemorylimit(void)
24{
25int line;
26int i;
27MemoryRange *mp = bootInfo->memoryMap;
28
29// Activate and clear page 1
30line = 1;
31for (i = 0; i < bootInfo->memoryMapCount; i++) {
32if((mp->type == 1) && ((unsigned long)mp->base == 0x100000)) {
33return (unsigned long)(mp->base + mp->length);
34}
35mp++;
36}
37return 0x10000000;
38}
39
40static void WakeKernelSnow(IOHibernateImageHeaderSnow * header)
41{
42uint32_t proc;
43unsigned long cnt, newSP;
44unsigned long *src, *dst;
45unsigned int count;
46unsigned int page;
47unsigned int compressedSize;
48int32_t byteCnt;
49u_int32_t lowHalf, highHalf;
50u_int32_t sum;
51
52printf("\nWake Kernel!\n");
53
54dst = (unsigned long *) (header->restore1CodePhysPage << 12);
55count = header->restore1PageCount;
56proc = (header->restore1CodeOffset + ((uint32_t) dst));
57newSP = header->restore1StackOffset + (header->restore1CodePhysPage << 12);
58
59src = (unsigned long *) (((u_int32_t) &header->fileExtentMap[0])
60 + header->fileExtentMapSize);
61sum = 0;
62
63for (page = 0; page < count; page++)
64{
65compressedSize = 4096;
66
67lowHalf = 1;
68highHalf = 0;
69
70for (cnt = 0; cnt < compressedSize; cnt += 0x20) {
71dst[0] = src[0];
72dst[1] = src[1];
73dst[2] = src[2];
74dst[3] = src[3];
75dst[4] = src[4];
76dst[5] = src[5];
77dst[6] = src[6];
78dst[7] = src[7];
79for (byteCnt = 0; byteCnt < 0x20; byteCnt++) {
80lowHalf += ((u_int8_t *) dst)[byteCnt];
81highHalf += lowHalf;
82}
83src += 8;
84dst += 8;
85}
86
87lowHalf %= 65521L;
88highHalf %= 65521L;
89sum += (highHalf << 16) | lowHalf;
90}
91header->actualRestore1Sum = sum;
92startprog (proc, header);
93
94return;
95}
96
97static void WakeKernel(IOHibernateImageHeader * header)
98{
99uint32_t proc;
100unsigned long cnt, newSP;
101unsigned long *src, *dst;
102unsigned int count;
103unsigned int page;
104unsigned int compressedSize;
105int32_t byteCnt;
106u_int32_t lowHalf, highHalf;
107u_int32_t sum;
108
109printf("\nWake Kernel!\n");
110
111dst = (unsigned long *) (header->restore1CodePhysPage << 12);
112count = header->restore1PageCount;
113proc = (header->restore1CodeOffset + ((uint32_t) dst));
114
115newSP = header->restore1StackOffset + (header->restore1CodePhysPage << 12);
116
117src = (unsigned long *) (((u_int32_t) &header->fileExtentMap[0])
118 + header->fileExtentMapSize);
119sum = 0;
120
121for (page = 0; page < count; page++)
122{
123compressedSize = 4096;
124
125lowHalf = 1;
126highHalf = 0;
127
128for (cnt = 0; cnt < compressedSize; cnt += 0x20) {
129dst[0] = src[0];
130dst[1] = src[1];
131dst[2] = src[2];
132dst[3] = src[3];
133dst[4] = src[4];
134dst[5] = src[5];
135dst[6] = src[6];
136dst[7] = src[7];
137for (byteCnt = 0; byteCnt < 0x20; byteCnt++) {
138lowHalf += ((u_int8_t *) dst)[byteCnt];
139highHalf += lowHalf;
140}
141src += 8;
142dst += 8;
143}
144
145lowHalf %= 65521L;
146highHalf %= 65521L;
147sum += (highHalf << 16) | lowHalf;
148}
149header->actualRestore1Sum = sum;
150startprog (proc, header);
151
152return;
153}
154
155void HibernateBoot(char *image_filename)
156{
157long long size, imageSize, codeSize, allocSize;
158long mem_base;
159IOHibernateImageHeader _header;
160IOHibernateImageHeader * header = &_header;
161long buffer;
162
163size = ReadFileAtOffset (image_filename, header, 0, sizeof(IOHibernateImageHeader));
164printf("header read size %x\n", size);
165
166imageSize = header->image1Size;
167codeSize = header->restore1PageCount << 12;
168if (kIOHibernateHeaderSignature != header->signature)
169{
170printf ("Incorrect image signature, expected version 10.7\n");
171getchar();
172return;
173}
174if (header->encryptStart)
175{
176printf ("Resuming from Encrypted image is unsupported.\n"
177"Uncheck \"Use secure virtual memory\" in \"Security\" pane on system preferences.\n"
178"Press any key to proceed with normal boot.\n");
179getchar();
180return;
181}
182// depends on NVRAM
183#if 0
184{
185uint32_t machineSignature;
186size = GetProp(gChosenPH, kIOHibernateMachineSignatureKey,
187 (char *)&machineSignature, sizeof(machineSignature));
188if (size != sizeof(machineSignature)) machineSignature = 0;
189if (machineSignature != header->machineSignature)
190break;
191}
192#endif
193
194allocSize = imageSize + ((4095 + sizeof(hibernate_graphics_t)) & ~4095);
195
196mem_base = (long)(getmemorylimit() - allocSize);//TODO: lower this
197
198printf("mem_base %x\n", mem_base);
199
200bcopy(header, (void *) mem_base, sizeof(IOHibernateImageHeader));
201header = (IOHibernateImageHeader *) mem_base;
202
203imageSize -= sizeof(IOHibernateImageHeader);
204buffer = (long)(header + 1);
205
206if (header->previewSize)
207{
208uint64_t preview_offset = header->fileExtentMapSize - sizeof(header->fileExtentMap) + codeSize;
209uint8_t progressSaveUnder[kIOHibernateProgressCount][kIOHibernateProgressSaveUnderSize];
210
211ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeader), preview_offset+header->previewSize);
212drawPreview ((void *)(long)(buffer+preview_offset + header->previewPageListSize), &(progressSaveUnder[0][0]));
213previewTotalSectors = (int)(imageSize-(preview_offset+header->previewSize))/512;
214previewLoadedSectors = 0;
215previewSaveunder = &(progressSaveUnder[0][0]);
216if (preview_offset+header->previewSize<imageSize)
217ReadFileAtOffset (image_filename, (char *)(long)(buffer+preview_offset+header->previewSize),
218 sizeof(IOHibernateImageHeader)+preview_offset+header->previewSize,
219 imageSize-(preview_offset+header->previewSize));
220previewTotalSectors = 0;
221previewLoadedSectors = 0;
222previewSaveunder = 0;
223#if 0
224/* AsereBLN:
225check_vga_nvidia() didn't work as expected (recursion level > 0 & return value).
226Unforutnaltely I cannot find a note why to switch back to text mode for nVidia cards only
227and because it check_vga_nvidia does not work (cards normally are behind a bridge) I will
228remove it completely */
229setVideoMode( VGA_TEXT_MODE, 0 );
230#endif
231}
232else
233ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeader), imageSize);
234
235// Depends on NVRAM
236#if 0
237if (header->encryptStart) {
238// decryption data
239static const unsigned char first_iv[AES_BLOCK_SIZE]
240= { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c,
2410xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda };
242hibernate_cryptvars_t _cryptvars;
243hibernate_cryptvars_t * cryptvars = &_cryptvars;
244
245aes_decrypt_key(&decryptkey,
246decryptkeysize,
247&cryptvars->ctx.decrypt);
248
249// set the vector for the following decryptions
250bcopy(((uint8_t *) header) + header->image1Size - AES_BLOCK_SIZE,
251&cryptvars->aes_iv[0], AES_BLOCK_SIZE);
252
253// decrypt the buffer
254uint32_t len = (uint32_t)(header->image1Size - header->encryptStart);
255aes_decrypt_cbc(((uint8_t *) header) + header->encryptStart,
256&first_iv[0],
257len >> 4,
258((uint8_t *) header) + header->encryptStart,
259&cryptvars->ctx.decrypt);
260bzero(&cryptvars->aes_iv[0], sizeof(cryptvars));
261bzero(&decryptkey, sizeof(decryptkey));
262}
263#endif
264
265WakeKernel(header);
266}
267
268void HibernateBootSnow(char *image_filename)
269{
270long long size, imageSize, codeSize, allocSize;
271long mem_base;
272IOHibernateImageHeaderSnow _header;
273IOHibernateImageHeaderSnow * header = &_header;
274long buffer;
275
276if(gMacOSVersion[3] >= '7') // TODO: unlocked, but please check the compatibility with the 10.8
277{
278HibernateBoot(image_filename);
279return;
280}
281
282size = ReadFileAtOffset (image_filename, header, 0, sizeof(IOHibernateImageHeaderSnow));
283printf("header read size %x\n", size);
284
285imageSize = header->image1Size;
286codeSize = header->restore1PageCount << 12;
287if (kIOHibernateHeaderSignature != header->signature) {
288printf ("Incorrect image signature\n");
289return;
290}
291if (header->encryptStart) {
292printf ("Resuming from Encrypted image is unsupported.\n"
293"Uncheck \"Use secure virtual memory\" in \"Security\" pane on system preferences.\n"
294"Press any key to proceed with normal boot.\n");
295getchar();
296return;
297}
298// depends on NVRAM
299#if 0
300{
301uint32_t machineSignature;
302size = GetProp(gChosenPH, kIOHibernateMachineSignatureKey,
303 (char *)&machineSignature, sizeof(machineSignature));
304if (size != sizeof(machineSignature)) {
305machineSignature = 0;
306}
307if (machineSignature != header->machineSignature) {
308break;
309}
310}
311#endif
312
313allocSize = imageSize + ((4095 + sizeof(hibernate_graphics_t)) & ~4095);
314
315mem_base = (long)(getmemorylimit() - allocSize);//TODO: lower this
316
317printf("mem_base %x\n", mem_base);
318if (((long long)mem_base + allocSize) < (1024 * bootInfo->extmem + 0x100000)) {
319printf ("Not enough space to restore image. Press any key to proceed with normal boot.\n");
320getchar();
321return;
322}
323
324bcopy(header, (void *) mem_base, sizeof(IOHibernateImageHeaderSnow));
325header = (IOHibernateImageHeaderSnow *) mem_base;
326
327imageSize -= sizeof(IOHibernateImageHeaderSnow);
328buffer = (long)(header + 1);
329
330if (header->previewSize) {
331uint64_t preview_offset = header->fileExtentMapSize - sizeof(header->fileExtentMap) + codeSize;
332uint8_t progressSaveUnder[kIOHibernateProgressCount][kIOHibernateProgressSaveUnderSize];
333
334ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeaderSnow), preview_offset+header->previewSize);
335drawPreview ((void *)(long)(buffer+preview_offset + header->previewPageListSize), &(progressSaveUnder[0][0]));
336previewTotalSectors = (imageSize-(preview_offset+header->previewSize))/512;
337previewLoadedSectors = 0;
338previewSaveunder = &(progressSaveUnder[0][0]);
339if (preview_offset+header->previewSize<imageSize) {
340ReadFileAtOffset (image_filename, (char *)(long)(buffer+preview_offset+header->previewSize),
341 sizeof(IOHibernateImageHeaderSnow)+preview_offset+header->previewSize,
342 imageSize-(preview_offset+header->previewSize));
343}
344previewTotalSectors = 0;
345previewLoadedSectors = 0;
346previewSaveunder = 0;
347#if 0
348//AsereBLN:
349//check_vga_nvidia() didn't work as expected (recursion level > 0 & return value).
350//Unforutnaltely I cannot find a note why to switch back to text mode for nVidia cards only
351//and because it check_vga_nvidia does not work (cards normally are behind a bridge) I will
352//remove it completely
353//setVideoMode( VGA_TEXT_MODE, 0 );
354#endif
355} else {
356ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeaderSnow), imageSize);
357}
358// Depends on NVRAM
359#if 0
360if (header->encryptStart) {
361// decryption data
362static const unsigned char first_iv[AES_BLOCK_SIZE]
363= { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c,
3640xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda };
365hibernate_cryptvars_t _cryptvars;
366hibernate_cryptvars_t * cryptvars = &_cryptvars;
367
368aes_decrypt_key(&decryptkey,
369decryptkeysize,
370&cryptvars->ctx.decrypt);
371
372// set the vector for the following decryptions
373bcopy(((uint8_t *) header) + header->image1Size - AES_BLOCK_SIZE,
374&cryptvars->aes_iv[0], AES_BLOCK_SIZE);
375
376// decrypt the buffer
377uint32_t len = (uint32_t)(header->image1Size - header->encryptStart);
378aes_decrypt_cbc(((uint8_t *) header) + header->encryptStart,
379&first_iv[0],
380len >> 4,
381((uint8_t *) header) + header->encryptStart,
382&cryptvars->ctx.decrypt);
383bzero(&cryptvars->aes_iv[0], sizeof(cryptvars));
384bzero(&decryptkey, sizeof(decryptkey));
385}
386#endif
387
388WakeKernelSnow(header);
389}
390

Archive Download this file

Revision: 2364