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

Archive Download this file

Revision: 1525