]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 2.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * drivers.c - Driver Loading Functions. | |
26 | * | |
27 | * Copyright (c) 2000 Apple Computer, Inc. | |
28 | * | |
29 | * DRI: Josh de Cesare | |
30 | */ | |
31 | ||
32 | #include <mach-o/fat.h> | |
33 | #include <libkern/OSByteOrder.h> | |
34 | #include <mach/machine.h> | |
35 | ||
36 | #include "sl.h" | |
37 | #include "boot.h" | |
38 | #include "bootstruct.h" | |
39 | #include "xml.h" | |
40 | ||
41 | struct Module { | |
42 | struct Module *nextModule; | |
43 | long willLoad; | |
44 | TagPtr dict; | |
45 | char *plistAddr; | |
46 | long plistLength; | |
47 | char *driverPath; | |
48 | }; | |
49 | typedef struct Module Module, *ModulePtr; | |
50 | ||
51 | struct DriverInfo { | |
52 | char *plistAddr; | |
53 | long plistLength; | |
54 | void *moduleAddr; | |
55 | long moduleLength; | |
56 | }; | |
57 | typedef struct DriverInfo DriverInfo, *DriverInfoPtr; | |
58 | ||
59 | #define kDriverPackageSignature1 'MKXT' | |
60 | #define kDriverPackageSignature2 'MOSX' | |
61 | ||
62 | struct DriversPackage { | |
63 | unsigned long signature1; | |
64 | unsigned long signature2; | |
65 | unsigned long length; | |
66 | unsigned long alder32; | |
67 | unsigned long version; | |
68 | unsigned long numDrivers; | |
69 | unsigned long reserved1; | |
70 | unsigned long reserved2; | |
71 | }; | |
72 | typedef struct DriversPackage DriversPackage; | |
73 | ||
74 | enum { | |
75 | kCFBundleType2, | |
76 | kCFBundleType3 | |
77 | }; | |
78 | ||
79 | static unsigned long Alder32( unsigned char * buffer, long length ); | |
80 | ||
81 | static long FileLoadDrivers(char *dirSpec, long plugin); | |
82 | static long NetLoadDrivers(char *dirSpec); | |
83 | static long LoadDriverMKext(char *fileSpec); | |
84 | static long LoadDriverPList(char *dirSpec, char *name, long bundleType); | |
85 | static long LoadMatchedModules(void); | |
86 | static long MatchPersonalities(void); | |
87 | static long MatchLibraries(void); | |
88 | #ifdef NOTDEF | |
89 | static ModulePtr FindModule(char *name); | |
90 | static void ThinFatFile(void **loadAddrP, unsigned long *lengthP); | |
91 | #endif | |
92 | static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities); | |
93 | static long InitDriverSupport(void); | |
94 | ||
95 | static ModulePtr gModuleHead, gModuleTail; | |
96 | static TagPtr gPersonalityHead, gPersonalityTail; | |
97 | static char * gExtensionsSpec; | |
98 | static char * gDriverSpec; | |
99 | static char * gFileSpec; | |
100 | static char * gTempSpec; | |
101 | static char * gFileName; | |
102 | ||
103 | ||
104 | static unsigned long | |
105 | Alder32( unsigned char * buffer, long length ) | |
106 | { | |
107 | long cnt; | |
108 | unsigned long result, lowHalf, highHalf; | |
109 | ||
110 | lowHalf = 1; | |
111 | highHalf = 0; | |
112 | ||
113 | for ( cnt = 0; cnt < length; cnt++ ) | |
114 | { | |
115 | if ((cnt % 5000) == 0) | |
116 | { | |
117 | lowHalf %= 65521L; | |
118 | highHalf %= 65521L; | |
119 | } | |
120 | ||
121 | lowHalf += buffer[cnt]; | |
122 | highHalf += lowHalf; | |
123 | } | |
124 | ||
125 | lowHalf %= 65521L; | |
126 | highHalf %= 65521L; | |
127 | ||
128 | result = (highHalf << 16) | lowHalf; | |
129 | ||
130 | return result; | |
131 | } | |
132 | ||
133 | ||
134 | //========================================================================== | |
135 | // InitDriverSupport | |
136 | ||
137 | static long | |
138 | InitDriverSupport( void ) | |
139 | { | |
140 | gExtensionsSpec = (char *) malloc( 4096 ); | |
141 | gDriverSpec = (char *) malloc( 4096 ); | |
142 | gFileSpec = (char *) malloc( 4096 ); | |
143 | gTempSpec = (char *) malloc( 4096 ); | |
144 | gFileName = (char *) malloc( 4096 ); | |
145 | ||
146 | if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName ) | |
147 | stop("InitDriverSupport error"); | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | //========================================================================== | |
153 | // LoadDrivers | |
154 | ||
155 | long LoadDrivers( char * dirSpec ) | |
156 | { | |
157 | if ( InitDriverSupport() != 0 ) | |
158 | return 0; | |
159 | ||
160 | if ( gBootFileType == kNetworkDeviceType ) | |
161 | { | |
162 | if (NetLoadDrivers(dirSpec) != 0) { | |
163 | error("Could not load drivers from the network\n"); | |
164 | return -1; | |
165 | } | |
166 | } | |
167 | else if ( gBootFileType == kBlockDeviceType ) | |
168 | { | |
169 | if (gMKextName[0] != '\0') | |
170 | { | |
171 | verbose("LoadDrivers: Loading from [%s]\n", gMKextName); | |
172 | if ( LoadDriverMKext(gMKextName) != 0 ) | |
173 | { | |
174 | error("Could not load %s\n", gMKextName); | |
175 | return -1; | |
176 | } | |
177 | } | |
178 | else | |
179 | { | |
180 | strcpy(gExtensionsSpec, dirSpec); | |
181 | strcat(gExtensionsSpec, "System/Library/"); | |
182 | FileLoadDrivers(gExtensionsSpec, 0); | |
183 | } | |
184 | } | |
185 | else | |
186 | { | |
187 | return 0; | |
188 | } | |
189 | ||
190 | MatchPersonalities(); | |
191 | ||
192 | MatchLibraries(); | |
193 | ||
194 | LoadMatchedModules(); | |
195 | ||
196 | return 0; | |
197 | } | |
198 | ||
199 | //========================================================================== | |
200 | // FileLoadDrivers | |
201 | ||
202 | static long | |
203 | FileLoadDrivers( char * dirSpec, long plugin ) | |
204 | { | |
205 | long ret, length, index, flags, time, bundleType; | |
206 | const char * name; | |
207 | ||
208 | if ( !plugin ) | |
209 | { | |
210 | long time2; | |
211 | ||
212 | ret = GetFileInfo(dirSpec, "Extensions.mkext", &flags, &time); | |
213 | if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat)) | |
214 | { | |
215 | ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2); | |
216 | if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeDirectory) || | |
217 | (((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1)))) | |
218 | { | |
219 | sprintf(gDriverSpec, "%sExtensions.mkext", dirSpec); | |
220 | verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec); | |
221 | if (LoadDriverMKext(gDriverSpec) == 0) return 0; | |
222 | } | |
223 | } | |
224 | ||
225 | strcat(dirSpec, "Extensions"); | |
226 | } | |
227 | ||
228 | verbose("LoadDrivers: Loading from [%s]\n", dirSpec); | |
229 | ||
230 | index = 0; | |
231 | while (1) { | |
232 | ret = GetDirEntry(dirSpec, &index, &name, &flags, &time); | |
233 | if (ret == -1) break; | |
234 | ||
235 | // Make sure this is a directory. | |
236 | if ((flags & kFileTypeMask) != kFileTypeDirectory) continue; | |
237 | ||
238 | // Make sure this is a kext. | |
239 | length = strlen(name); | |
240 | if (strcmp(name + length - 5, ".kext")) continue; | |
241 | ||
242 | // Save the file name. | |
243 | strcpy(gFileName, name); | |
244 | ||
245 | // Determine the bundle type. | |
246 | sprintf(gTempSpec, "%s/%s", dirSpec, gFileName); | |
247 | ret = GetFileInfo(gTempSpec, "Contents", &flags, &time); | |
248 | if (ret == 0) bundleType = kCFBundleType2; | |
249 | else bundleType = kCFBundleType3; | |
250 | ||
251 | if (!plugin) | |
252 | sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName, | |
253 | (bundleType == kCFBundleType2) ? "Contents/" : ""); | |
254 | ||
255 | ret = LoadDriverPList(dirSpec, gFileName, bundleType); | |
256 | if (ret != 0) | |
257 | { | |
258 | //printf("LoadDrivers: failed for '%s'/'%s'\n", dirSpec, gFileName); | |
259 | } | |
260 | ||
261 | if (!plugin) | |
262 | ret = FileLoadDrivers(gDriverSpec, 1); | |
263 | } | |
264 | ||
265 | return 0; | |
266 | } | |
267 | ||
268 | //========================================================================== | |
269 | // | |
270 | ||
271 | static long | |
272 | NetLoadDrivers( char * dirSpec ) | |
273 | { | |
274 | long tries; | |
275 | ||
276 | #if NODEF | |
277 | long cnt; | |
278 | ||
279 | // Get the name of the kernel | |
280 | cnt = strlen(gBootFile); | |
281 | while (cnt--) { | |
282 | if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ',')) { | |
283 | cnt++; | |
284 | break; | |
285 | } | |
286 | } | |
287 | #endif | |
288 | ||
289 | // INTEL modification | |
290 | sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile); | |
291 | ||
292 | verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec); | |
293 | ||
294 | tries = 3; | |
295 | while (tries--) | |
296 | { | |
297 | if (LoadDriverMKext(gDriverSpec) == 0) break; | |
298 | } | |
299 | if (tries == -1) return -1; | |
300 | ||
301 | return 0; | |
302 | } | |
303 | ||
304 | //========================================================================== | |
305 | // loadDriverMKext | |
306 | ||
307 | static long | |
308 | LoadDriverMKext( char * fileSpec ) | |
309 | { | |
310 | unsigned long driversAddr, driversLength; | |
311 | long length; | |
312 | char segName[32]; | |
313 | DriversPackage * package; | |
314 | ||
315 | #define GetPackageElement(e) OSSwapBigToHostInt32(package->e) | |
316 | ||
317 | // Load the MKext. | |
318 | length = LoadThinFatFile(fileSpec, (void **)&package); | |
319 | if (length == -1) return -1; | |
320 | ||
321 | // Verify the MKext. | |
322 | if (( GetPackageElement(signature1) != kDriverPackageSignature1) || | |
323 | ( GetPackageElement(signature2) != kDriverPackageSignature2) || | |
324 | ( GetPackageElement(length) > kLoadSize ) || | |
325 | ( GetPackageElement(alder32) != | |
326 | Alder32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) ) | |
327 | { | |
328 | return -1; | |
329 | } | |
330 | ||
331 | // Make space for the MKext. | |
332 | driversLength = GetPackageElement(length); | |
333 | driversAddr = AllocateKernelMemory(driversLength); | |
334 | ||
335 | // Copy the MKext. | |
336 | memcpy((void *)driversAddr, (void *)package, driversLength); | |
337 | ||
338 | // Add the MKext to the memory map. | |
339 | sprintf(segName, "DriversPackage-%lx", driversAddr); | |
340 | AllocateMemoryRange(segName, driversAddr, driversLength, | |
341 | kBootDriverTypeMKEXT); | |
342 | ||
343 | return 0; | |
344 | } | |
345 | ||
346 | //========================================================================== | |
347 | // LoadDriverPList | |
348 | ||
349 | static long | |
350 | LoadDriverPList( char * dirSpec, char * name, long bundleType ) | |
351 | { | |
352 | long length, driverPathLength; | |
353 | ModulePtr module; | |
354 | TagPtr personalities; | |
355 | char * buffer = 0; | |
356 | char * tmpDriverPath = 0; | |
357 | long ret = -1; | |
358 | ||
359 | do { | |
360 | // Save the driver path. | |
361 | ||
362 | sprintf(gFileSpec, "%s/%s/%s", dirSpec, name, | |
363 | (bundleType == kCFBundleType2) ? "Contents/MacOS/" : ""); | |
364 | driverPathLength = strlen(gFileSpec) + 1; | |
365 | ||
366 | tmpDriverPath = malloc(driverPathLength); | |
367 | if (tmpDriverPath == 0) break; | |
368 | ||
369 | strcpy(tmpDriverPath, gFileSpec); | |
370 | ||
371 | // Construct the file spec to the plist, then load it. | |
372 | ||
373 | sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name, | |
374 | (bundleType == kCFBundleType2) ? "Contents/" : ""); | |
375 | ||
376 | length = LoadFile(gFileSpec); | |
377 | if (length == -1) break; | |
378 | ||
379 | length = length + 1; | |
380 | buffer = malloc(length); | |
381 | if (buffer == 0) break; | |
382 | ||
383 | strlcpy(buffer, (char *)kLoadAddr, length); | |
384 | ||
385 | // Parse the plist. | |
386 | ||
387 | ret = ParseXML(buffer, &module, &personalities); | |
388 | if (ret != 0) { break; } | |
389 | ||
390 | // Allocate memory for the driver path and the plist. | |
391 | ||
392 | module->driverPath = tmpDriverPath; | |
393 | module->plistAddr = (void *)malloc(length); | |
394 | ||
395 | if ((module->driverPath == 0) || (module->plistAddr == 0)) | |
396 | break; | |
397 | ||
398 | // Save the driver path in the module. | |
399 | //strcpy(module->driverPath, tmpDriverPath); | |
400 | tmpDriverPath = 0; | |
401 | ||
402 | // Add the plist to the module. | |
403 | ||
404 | strlcpy(module->plistAddr, (char *)kLoadAddr, length); | |
405 | module->plistLength = length; | |
406 | ||
407 | // Add the module to the end of the module list. | |
408 | ||
409 | if (gModuleHead == 0) | |
410 | gModuleHead = module; | |
411 | else | |
412 | gModuleTail->nextModule = module; | |
413 | gModuleTail = module; | |
414 | ||
415 | // Add the persionalities to the personality list. | |
416 | ||
417 | if (personalities) personalities = personalities->tag; | |
418 | while (personalities != 0) | |
419 | { | |
420 | if (gPersonalityHead == 0) | |
421 | gPersonalityHead = personalities->tag; | |
422 | else | |
423 | gPersonalityTail->tagNext = personalities->tag; | |
424 | ||
425 | gPersonalityTail = personalities->tag; | |
426 | personalities = personalities->tagNext; | |
427 | } | |
428 | ||
429 | ret = 0; | |
430 | } | |
431 | while (0); | |
432 | ||
433 | if ( buffer ) free( buffer ); | |
434 | if ( tmpDriverPath ) free( tmpDriverPath ); | |
435 | ||
436 | return ret; | |
437 | } | |
438 | ||
439 | ||
440 | //========================================================================== | |
441 | // LoadMatchedModules | |
442 | ||
443 | static long | |
444 | LoadMatchedModules( void ) | |
445 | { | |
446 | TagPtr prop; | |
447 | ModulePtr module; | |
448 | char *fileName, segName[32]; | |
449 | DriverInfoPtr driver; | |
450 | long length, driverAddr, driverLength; | |
451 | void *driverModuleAddr = 0; | |
452 | ||
453 | ||
454 | module = gModuleHead; | |
455 | ||
456 | while (module != 0) | |
457 | { | |
458 | if (module->willLoad) | |
459 | { | |
460 | prop = XMLGetProperty(module->dict, kPropCFBundleExecutable); | |
461 | ||
462 | if (prop != 0) | |
463 | { | |
464 | fileName = prop->string; | |
465 | sprintf(gFileSpec, "%s%s", module->driverPath, fileName); | |
466 | length = LoadThinFatFile(gFileSpec, &driverModuleAddr); | |
467 | //length = LoadFile(gFileSpec); | |
468 | //driverModuleAddr = (void *)kLoadAddr; | |
469 | //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc(); | |
470 | } | |
471 | else | |
472 | length = 0; | |
473 | ||
474 | if (length != -1) | |
475 | { | |
476 | //driverModuleAddr = (void *)kLoadAddr; | |
477 | //if (length != 0) | |
478 | //{ | |
479 | // ThinFatFile(&driverModuleAddr, &length); | |
480 | //} | |
481 | ||
482 | // Make make in the image area. | |
483 | driverLength = sizeof(DriverInfo) + module->plistLength + length; | |
484 | driverAddr = AllocateKernelMemory(driverLength); | |
485 | ||
486 | // Set up the DriverInfo. | |
487 | driver = (DriverInfoPtr)driverAddr; | |
488 | driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo)); | |
489 | driver->plistLength = module->plistLength; | |
490 | if (length != 0) | |
491 | { | |
492 | driver->moduleAddr = (void *)(driverAddr + sizeof(DriverInfo) + | |
493 | module->plistLength); | |
494 | driver->moduleLength = length; | |
495 | } | |
496 | else | |
497 | { | |
498 | driver->moduleAddr = 0; | |
499 | driver->moduleLength = 0; | |
500 | } | |
501 | ||
502 | // Save the plist and module. | |
503 | strcpy(driver->plistAddr, module->plistAddr); | |
504 | if (length != 0) | |
505 | { | |
506 | memcpy(driver->moduleAddr, driverModuleAddr, length); | |
507 | } | |
508 | ||
509 | // Add an entry to the memory map. | |
510 | sprintf(segName, "Driver-%lx", (unsigned long)driver); | |
511 | AllocateMemoryRange(segName, driverAddr, driverLength, | |
512 | kBootDriverTypeKEXT); | |
513 | } | |
514 | } | |
515 | module = module->nextModule; | |
516 | } | |
517 | ||
518 | return 0; | |
519 | } | |
520 | ||
521 | //========================================================================== | |
522 | // MatchPersonalities | |
523 | ||
524 | static long | |
525 | MatchPersonalities( void ) | |
526 | { | |
527 | /* IONameMatch support not implemented */ | |
528 | return 0; | |
529 | } | |
530 | ||
531 | //========================================================================== | |
532 | // MatchLibraries | |
533 | ||
534 | static long | |
535 | MatchLibraries( void ) | |
536 | { | |
537 | TagPtr prop, prop2; | |
538 | ModulePtr module, module2; | |
539 | long done; | |
540 | ||
541 | do { | |
542 | done = 1; | |
543 | module = gModuleHead; | |
544 | ||
545 | while (module != 0) | |
546 | { | |
547 | if (module->willLoad == 1) | |
548 | { | |
549 | prop = XMLGetProperty(module->dict, kPropOSBundleLibraries); | |
550 | if (prop != 0) | |
551 | { | |
552 | prop = prop->tag; | |
553 | while (prop != 0) | |
554 | { | |
555 | module2 = gModuleHead; | |
556 | while (module2 != 0) | |
557 | { | |
558 | prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier); | |
559 | if ((prop2 != 0) && (!strcmp(prop->string, prop2->string))) | |
560 | { | |
561 | if (module2->willLoad == 0) module2->willLoad = 1; | |
562 | break; | |
563 | } | |
564 | module2 = module2->nextModule; | |
565 | } | |
566 | prop = prop->tagNext; | |
567 | } | |
568 | } | |
569 | module->willLoad = 2; | |
570 | done = 0; | |
571 | } | |
572 | module = module->nextModule; | |
573 | } | |
574 | } | |
575 | while (!done); | |
576 | ||
577 | return 0; | |
578 | } | |
579 | ||
580 | ||
581 | //========================================================================== | |
582 | // FindModule | |
583 | ||
584 | #if NOTDEF | |
585 | static ModulePtr | |
586 | FindModule( char * name ) | |
587 | { | |
588 | ModulePtr module; | |
589 | TagPtr prop; | |
590 | ||
591 | module = gModuleHead; | |
592 | ||
593 | while (module != 0) | |
594 | { | |
595 | prop = GetProperty(module->dict, kPropCFBundleIdentifier); | |
596 | if ((prop != 0) && !strcmp(name, prop->string)) break; | |
597 | module = module->nextModule; | |
598 | } | |
599 | ||
600 | return module; | |
601 | } | |
602 | #endif /* NOTDEF */ | |
603 | ||
604 | //========================================================================== | |
605 | // ParseXML | |
606 | ||
607 | static long | |
608 | ParseXML( char * buffer, ModulePtr * module, TagPtr * personalities ) | |
609 | { | |
610 | long length, pos; | |
611 | TagPtr moduleDict, required; | |
612 | ModulePtr tmpModule; | |
613 | ||
614 | pos = 0; | |
615 | ||
616 | while (1) | |
617 | { | |
618 | length = XMLParseNextTag(buffer + pos, &moduleDict); | |
619 | if (length == -1) break; | |
620 | ||
621 | pos += length; | |
622 | ||
623 | if (moduleDict == 0) continue; | |
624 | if (moduleDict->type == kTagTypeDict) break; | |
625 | ||
626 | XMLFreeTag(moduleDict); | |
627 | } | |
628 | ||
629 | if (length == -1) return -1; | |
630 | ||
631 | required = XMLGetProperty(moduleDict, kPropOSBundleRequired); | |
632 | if ( (required == 0) || | |
633 | (required->type != kTagTypeString) || | |
634 | !strcmp(required->string, "Safe Boot")) | |
635 | { | |
636 | XMLFreeTag(moduleDict); | |
637 | return -2; | |
638 | } | |
639 | ||
640 | tmpModule = (ModulePtr)malloc(sizeof(Module)); | |
641 | if (tmpModule == 0) | |
642 | { | |
643 | XMLFreeTag(moduleDict); | |
644 | return -1; | |
645 | } | |
646 | tmpModule->dict = moduleDict; | |
647 | ||
648 | // For now, load any module that has OSBundleRequired != "Safe Boot". | |
649 | ||
650 | tmpModule->willLoad = 1; | |
651 | ||
652 | *module = tmpModule; | |
653 | ||
654 | // Get the personalities. | |
655 | ||
656 | *personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities); | |
657 | ||
658 | return 0; | |
659 | } | |
660 | ||
661 | #if NOTDEF | |
662 | static char gPlatformName[64]; | |
663 | #endif | |
664 | ||
665 | long | |
666 | DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) | |
667 | { | |
668 | long ret; | |
669 | compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; | |
670 | u_int32_t uncompressed_size, size; | |
671 | void *buffer; | |
672 | ||
673 | #if 0 | |
674 | printf("kernel header:\n"); | |
675 | printf("signature: 0x%x\n", kernel_header->signature); | |
676 | printf("compress_type: 0x%x\n", kernel_header->compress_type); | |
677 | printf("adler32: 0x%x\n", kernel_header->adler32); | |
678 | printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); | |
679 | printf("compressed_size: 0x%x\n", kernel_header->compressed_size); | |
680 | getc(); | |
681 | #endif | |
682 | ||
683 | if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { | |
684 | if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) { | |
685 | error("kernel compression is bad\n"); | |
686 | return -1; | |
687 | } | |
688 | #if NOTDEF | |
689 | if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) | |
690 | return -1; | |
691 | if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) | |
692 | return -1; | |
693 | #endif | |
694 | ||
695 | uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); | |
696 | binary = buffer = malloc(uncompressed_size); | |
697 | ||
698 | size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0], | |
699 | OSSwapBigToHostInt32(kernel_header->compressed_size)); | |
700 | if (uncompressed_size != size) { | |
701 | error("size mismatch from lzss: %x\n", size); | |
702 | return -1; | |
703 | } | |
704 | if (OSSwapBigToHostInt32(kernel_header->adler32) != | |
705 | Alder32(binary, uncompressed_size)) { | |
706 | printf("adler mismatch\n"); | |
707 | return -1; | |
708 | } | |
709 | } | |
710 | ||
711 | ThinFatFile(&binary, 0); | |
712 | ||
713 | ret = DecodeMachO(binary, rentry, raddr, rsize); | |
714 | ||
715 | return ret; | |
716 | } |