Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1913