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

Archive Download this file

Revision: 1735