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

Archive Download this file

Revision: 1840