Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/boot2/drivers.c

Source at commit 735 created 13 years 2 months ago.
By meklort, GUI module bugfixes. Kext Patcher additions.
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#include "ramdisk.h"
41#include "drivers.h"
42#include "modules.h"
43
44extern char gMacOSVersion;
45
46#ifndef OPTION_ROM
47long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
48#endif
49
50unsigned long Adler32( unsigned char * buffer, long length );
51
52long FileLoadDrivers(char *dirSpec, long plugin);
53#ifndef OPTION_ROM
54long NetLoadDrivers(char *dirSpec);
55#endif
56long LoadDriverMKext(char *fileSpec);
57long LoadDriverPList(char *dirSpec, char *name, long bundleType);
58long LoadMatchedModules(void);
59long MatchPersonalities(void);
60long MatchLibraries(void);
61#ifdef NOTDEF
62static ModulePtr FindModule(char *name);
63static void ThinFatFile(void **loadAddrP, unsigned long *lengthP);
64#endif
65static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities);
66long InitDriverSupport(void);
67
68static ModulePtr gModuleHead, gModuleTail;
69static TagPtr gPersonalityHead, gPersonalityTail;
70char * gExtensionsSpec;
71char * gDriverSpec;
72char * gFileSpec;
73char * gTempSpec;
74char * gFileName;
75
76unsigned long
77Adler32( unsigned char * buffer, long length )
78{
79 long cnt;
80 unsigned long result, lowHalf, highHalf;
81
82 lowHalf = 1;
83 highHalf = 0;
84
85for ( cnt = 0; cnt < length; cnt++ )
86 {
87 if ((cnt % 5000) == 0)
88 {
89 lowHalf %= 65521L;
90 highHalf %= 65521L;
91 }
92
93 lowHalf += buffer[cnt];
94 highHalf += lowHalf;
95 }
96
97lowHalf %= 65521L;
98highHalf %= 65521L;
99
100result = (highHalf << 16) | lowHalf;
101
102 return result;
103}
104
105
106//==========================================================================
107// InitDriverSupport
108
109long
110InitDriverSupport( void )
111{
112 gExtensionsSpec = malloc( 4096 );
113 gDriverSpec = malloc( 4096 );
114 gFileSpec = malloc( 4096 );
115 gTempSpec = malloc( 4096 );
116 gFileName = malloc( 4096 );
117
118 if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
119 stop("InitDriverSupport error");
120
121 return 0;
122}
123
124//==========================================================================
125// LoadDrivers
126
127long LoadDrivers( char * dirSpec )
128{
129 char dirSpecExtra[1024];
130
131 if ( InitDriverSupport() != 0 )
132 return 0;
133
134#ifndef OPTION_ROM
135 // Load extra drivers if a hook has been installed.
136 if (LoadExtraDrivers_p != NULL)
137 {
138 (*LoadExtraDrivers_p)(&FileLoadDrivers);
139 }
140
141 if ( gBootFileType == kNetworkDeviceType )
142 {
143 if (NetLoadDrivers(dirSpec) != 0) {
144 error("Could not load drivers from the network\n");
145 return -1;
146 }
147 }
148 else
149#endif
150if ( gBootFileType == kBlockDeviceType )
151{
152// First try to load Extra extensions from the ramdisk if isn't aliased as bt(0,0).
153#ifndef OPTION_ROM
154// First try a specfic OS version folder ie 10.5
155sprintf(dirSpecExtra, "rd(0,0)/Extra/%s/", &gMacOSVersion);
156if (FileLoadDrivers(dirSpecExtra, 0) != 0)
157{
158// Next we'll try the base
159strcpy(dirSpecExtra, "rd(0,0)/Extra/");
160FileLoadDrivers(dirSpecExtra, 0);
161}
162#endif
163
164// First try a specfic OS version folder ie 10.5
165sprintf(dirSpecExtra, "/Extra/%s/", &gMacOSVersion);
166if (FileLoadDrivers(dirSpecExtra, 0) != 0)
167{
168// Next try to load Extra extensions from the selected root partition.
169strcpy(dirSpecExtra, "/Extra/");
170if (FileLoadDrivers(dirSpecExtra, 0) != 0)
171{
172// If failed, then try to load Extra extensions from the boot partition
173// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
174if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
175#ifndef OPTION_ROM
176|| (gRAMDiskVolume && gRAMDiskBTAliased) )
177#else
178)
179#endif
180{
181// First try a specfic OS version folder ie 10.5
182sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion);
183if (FileLoadDrivers(dirSpecExtra, 0) != 0)
184{
185// Next we'll try the base
186strcpy(dirSpecExtra, "bt(0,0)/Extra/");
187FileLoadDrivers(dirSpecExtra, 0);
188}
189}
190}
191
192}
193// TODO: fix this, the order does matter, and it's not correct now.
194// Also try to load Extensions from boot helper partitions.
195if (gBootVolume->flags & kBVFlagBooter)
196{
197strcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/");
198if (FileLoadDrivers(dirSpecExtra, 0) != 0)
199{
200strcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/");
201if (FileLoadDrivers(dirSpecExtra, 0) != 0)
202{
203strcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/");
204FileLoadDrivers(dirSpecExtra, 0);
205}
206}
207}
208
209if (gMKextName[0] != '\0')
210{
211verbose("LoadDrivers: Loading from [%s]\n", gMKextName);
212if ( LoadDriverMKext(gMKextName) != 0 )
213{
214error("Could not load %s\n", gMKextName);
215return -1;
216}
217}
218else
219{
220strcpy(gExtensionsSpec, dirSpec);
221strcat(gExtensionsSpec, "System/Library/");
222FileLoadDrivers(gExtensionsSpec, 0);
223}
224}
225else
226{
227return 0;
228}
229
230 MatchPersonalities();
231
232 MatchLibraries();
233
234 LoadMatchedModules();
235
236 return 0;
237}
238
239//==========================================================================
240// FileLoadMKext
241
242static long
243FileLoadMKext( const char * dirSpec, const char * extDirSpec )
244{
245long ret, flags, time, time2;
246char altDirSpec[512];
247
248sprintf (altDirSpec, "%s%s", dirSpec, extDirSpec);
249ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
250if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
251{
252ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
253if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeDirectory) ||
254(((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
255{
256sprintf(gDriverSpec, "%sExtensions.mkext", altDirSpec);
257verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec);
258if (LoadDriverMKext(gDriverSpec) == 0) return 0;
259}
260}
261return -1;
262}
263
264//==========================================================================
265// FileLoadDrivers
266
267long
268FileLoadDrivers( char * dirSpec, long plugin )
269{
270 long ret, length, flags, time, bundleType;
271 long long index;
272 long result = -1;
273 const char * name;
274
275 if ( !plugin )
276 {
277 // First try 10.6's path for loading Extensions.mkext.
278 if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0)
279return 0;
280
281 // Next try the legacy path.
282 else if (FileLoadMKext(dirSpec, "") == 0)
283return 0;
284
285 strcat(dirSpec, "Extensions");
286 }
287
288 index = 0;
289 while (1) {
290 ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
291 if (ret == -1) break;
292
293 // Make sure this is a directory.
294 if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
295
296 // Make sure this is a kext.
297 length = strlen(name);
298 if (strcmp(name + length - 5, ".kext")) continue;
299
300 // Save the file name.
301 strcpy(gFileName, name);
302
303 // Determine the bundle type.
304 sprintf(gTempSpec, "%s/%s", dirSpec, gFileName);
305 ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
306 if (ret == 0) bundleType = kCFBundleType2;
307 else bundleType = kCFBundleType3;
308
309 if (!plugin)
310 sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName,
311 (bundleType == kCFBundleType2) ? "Contents/" : "");
312
313 ret = LoadDriverPList(dirSpec, gFileName, bundleType);
314
315 if (result != 0)
316result = ret;
317
318 if (!plugin)
319FileLoadDrivers(gDriverSpec, 1);
320 }
321
322 return result;
323}
324
325//==========================================================================
326//
327#ifndef OPTION_ROM
328long
329NetLoadDrivers( char * dirSpec )
330{
331 long tries;
332
333#if NODEF
334 long cnt;
335
336 // Get the name of the kernel
337 cnt = strlen(gBootFile);
338 while (cnt--) {
339 if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ',')) {
340cnt++;
341break;
342 }
343 }
344#endif
345
346 // INTEL modification
347 sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile);
348
349 verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
350
351 tries = 3;
352 while (tries--)
353 {
354 if (LoadDriverMKext(gDriverSpec) == 0) break;
355 }
356 if (tries == -1) return -1;
357
358 return 0;
359}
360#endif
361//==========================================================================
362// loadDriverMKext
363
364long
365LoadDriverMKext( char * fileSpec )
366{
367 unsigned long driversAddr, driversLength;
368 long length;
369 char segName[32];
370 DriversPackage * package;
371
372#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
373
374 // Load the MKext.
375 length = LoadThinFatFile(fileSpec, (void **)&package);
376 if (length < sizeof (DriversPackage)) return -1;
377
378// call hook to notify modules that the mkext has been loaded
379execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) &length, NULL);
380
381
382 // Verify the MKext.
383 if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
384 ( GetPackageElement(signature2) != kDriverPackageSignature2) ||
385 ( GetPackageElement(length) > kLoadSize ) ||
386 ( GetPackageElement(adler32) !=
387 Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
388 {
389 return -1;
390 }
391
392 // Make space for the MKext.
393 driversLength = GetPackageElement(length);
394 driversAddr = AllocateKernelMemory(driversLength);
395
396 // Copy the MKext.
397 memcpy((void *)driversAddr, (void *)package, driversLength);
398
399 // Add the MKext to the memory map.
400 sprintf(segName, "DriversPackage-%lx", driversAddr);
401 AllocateMemoryRange(segName, driversAddr, driversLength,
402 kBootDriverTypeMKEXT);
403
404 return 0;
405}
406
407//==========================================================================
408// LoadDriverPList
409
410long
411LoadDriverPList( char * dirSpec, char * name, long bundleType )
412{
413 long length, executablePathLength, bundlePathLength;
414 ModulePtr module;
415 TagPtr personalities;
416 char * buffer = 0;
417 char * tmpExecutablePath = 0;
418 char * tmpBundlePath = 0;
419 long ret = -1;
420
421 do {
422 // Save the driver path.
423
424 sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
425 (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
426 executablePathLength = strlen(gFileSpec) + 1;
427
428 tmpExecutablePath = malloc(executablePathLength);
429 if (tmpExecutablePath == 0) break;
430
431 strcpy(tmpExecutablePath, gFileSpec);
432
433 sprintf(gFileSpec, "%s/%s", dirSpec, name);
434 bundlePathLength = strlen(gFileSpec) + 1;
435
436 tmpBundlePath = malloc(bundlePathLength);
437 if (tmpBundlePath == 0) break;
438
439 strcpy(tmpBundlePath, gFileSpec);
440
441 // Construct the file spec to the plist, then load it.
442
443 sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
444 (bundleType == kCFBundleType2) ? "Contents/" : "");
445
446 length = LoadFile(gFileSpec);
447 if (length == -1) break;
448
449 length = length + 1;
450 buffer = malloc(length);
451 if (buffer == 0) break;
452
453 strlcpy(buffer, (char *)kLoadAddr, length);
454
455 // Parse the plist.
456
457 ret = ParseXML(buffer, &module, &personalities);
458 if (ret != 0) { break; }
459
460 // Allocate memory for the driver path and the plist.
461
462 module->executablePath = tmpExecutablePath;
463 module->bundlePath = tmpBundlePath;
464 module->bundlePathLength = bundlePathLength;
465 module->plistAddr = malloc(length);
466
467 if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
468 break;
469
470 // Save the driver path in the module.
471 //strcpy(module->driverPath, tmpDriverPath);
472 tmpExecutablePath = 0;
473 tmpBundlePath = 0;
474
475 // Add the plist to the module.
476
477 strlcpy(module->plistAddr, (char *)kLoadAddr, length);
478 module->plistLength = length;
479
480 // Add the module to the end of the module list.
481
482 if (gModuleHead == 0)
483 gModuleHead = module;
484 else
485 gModuleTail->nextModule = module;
486 gModuleTail = module;
487
488 // Add the persionalities to the personality list.
489
490 if (personalities) personalities = personalities->tag;
491 while (personalities != 0)
492 {
493 if (gPersonalityHead == 0)
494 gPersonalityHead = personalities->tag;
495 else
496 gPersonalityTail->tagNext = personalities->tag;
497
498 gPersonalityTail = personalities->tag;
499 personalities = personalities->tagNext;
500 }
501
502 ret = 0;
503 }
504 while (0);
505
506 if ( buffer ) free( buffer );
507 if ( tmpExecutablePath ) free( tmpExecutablePath );
508 if ( tmpBundlePath ) free( tmpBundlePath );
509
510 return ret;
511}
512
513
514//==========================================================================
515// LoadMatchedModules
516
517long LoadMatchedModules( void )
518{
519 TagPtr prop;
520 ModulePtr module;
521 char *fileName, segName[32];
522 DriverInfoPtr driver;
523 long length, driverAddr, driverLength;
524 void *executableAddr = 0;
525
526
527 module = gModuleHead;
528
529 while (module != 0)
530 {
531 if (module->willLoad)
532 {
533 prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
534
535 if (prop != 0)
536 {
537 fileName = prop->string;
538 sprintf(gFileSpec, "%s%s", module->executablePath, fileName);
539 length = LoadThinFatFile(gFileSpec, &executableAddr);
540if (length == 0)
541{
542length = LoadFile(gFileSpec);
543executableAddr = (void *)kLoadAddr;
544}
545 //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
546 }
547 else
548 length = 0;
549
550 if (length != -1)
551 {
552//driverModuleAddr = (void *)kLoadAddr;
553 //if (length != 0)
554 //{
555// ThinFatFile(&driverModuleAddr, &length);
556//}
557
558 // Make make in the image area.
559
560execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
561
562 driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
563 driverAddr = AllocateKernelMemory(driverLength);
564
565 // Set up the DriverInfo.
566 driver = (DriverInfoPtr)driverAddr;
567 driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
568 driver->plistLength = module->plistLength;
569 if (length != 0)
570 {
571 driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
572 module->plistLength);
573 driver->executableLength = length;
574 }
575 else
576 {
577 driver->executableAddr = 0;
578 driver->executableLength = 0;
579 }
580 driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
581 module->plistLength + driver->executableLength);
582 driver->bundlePathLength = module->bundlePathLength;
583
584 // Save the plist, module and bundle.
585 strcpy(driver->plistAddr, module->plistAddr);
586 if (length != 0)
587 {
588 memcpy(driver->executableAddr, executableAddr, length);
589 }
590 strcpy(driver->bundlePathAddr, module->bundlePath);
591
592 // Add an entry to the memory map.
593 sprintf(segName, "Driver-%lx", (unsigned long)driver);
594 AllocateMemoryRange(segName, driverAddr, driverLength,
595 kBootDriverTypeKEXT);
596 }
597 }
598 module = module->nextModule;
599 }
600
601 return 0;
602}
603
604//==========================================================================
605// MatchPersonalities
606
607long MatchPersonalities( void )
608{
609 /* IONameMatch support not implemented */
610 return 0;
611}
612
613//==========================================================================
614// MatchLibraries
615
616long MatchLibraries( void )
617{
618 TagPtr prop, prop2;
619 ModulePtr module, module2;
620 long done;
621
622 do {
623 done = 1;
624 module = gModuleHead;
625
626 while (module != 0)
627 {
628 if (module->willLoad == 1)
629 {
630 prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
631 if (prop != 0)
632 {
633 prop = prop->tag;
634 while (prop != 0)
635 {
636 module2 = gModuleHead;
637 while (module2 != 0)
638 {
639 prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
640 if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
641 {
642 if (module2->willLoad == 0) module2->willLoad = 1;
643 break;
644 }
645 module2 = module2->nextModule;
646 }
647 prop = prop->tagNext;
648 }
649 }
650 module->willLoad = 2;
651 done = 0;
652 }
653 module = module->nextModule;
654 }
655 }
656 while (!done);
657
658 return 0;
659}
660
661
662//==========================================================================
663// FindModule
664
665#if NOTDEF
666static ModulePtr
667FindModule( char * name )
668{
669 ModulePtr module;
670 TagPtr prop;
671
672 module = gModuleHead;
673
674 while (module != 0)
675 {
676 prop = GetProperty(module->dict, kPropCFBundleIdentifier);
677 if ((prop != 0) && !strcmp(name, prop->string)) break;
678 module = module->nextModule;
679 }
680
681 return module;
682}
683#endif /* NOTDEF */
684
685//==========================================================================
686// ParseXML
687
688static long
689ParseXML( char * buffer, ModulePtr * module, TagPtr * personalities )
690{
691long length, pos;
692TagPtr moduleDict, required;
693ModulePtr tmpModule;
694
695 pos = 0;
696
697 while (1)
698 {
699 length = XMLParseNextTag(buffer + pos, &moduleDict);
700 if (length == -1) break;
701
702 pos += length;
703
704 if (moduleDict == 0) continue;
705 if (moduleDict->type == kTagTypeDict) break;
706
707 XMLFreeTag(moduleDict);
708 }
709
710 if (length == -1) return -1;
711
712 required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
713 if ( (required == 0) ||
714(required->type != kTagTypeString) ||
715!strcmp(required->string, "Safe Boot"))
716 {
717 XMLFreeTag(moduleDict);
718 return -2;
719 }
720
721 tmpModule = malloc(sizeof(Module));
722 if (tmpModule == 0)
723 {
724 XMLFreeTag(moduleDict);
725 return -1;
726 }
727 tmpModule->dict = moduleDict;
728
729 // For now, load any module that has OSBundleRequired != "Safe Boot".
730
731 tmpModule->willLoad = 1;
732
733 *module = tmpModule;
734
735 // Get the personalities.
736
737 *personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
738
739 return 0;
740}
741
742#if NOTDEF
743static char gPlatformName[64];
744#endif
745
746long
747DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
748{
749 long ret;
750 compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary;
751 u_int32_t uncompressed_size, size;
752 void *buffer;
753unsigned long len;
754
755#if 0
756 printf("kernel header:\n");
757 printf("signature: 0x%x\n", kernel_header->signature);
758 printf("compress_type: 0x%x\n", kernel_header->compress_type);
759 printf("adler32: 0x%x\n", kernel_header->adler32);
760 printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
761 printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
762 getc();
763#endif
764
765 if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) {
766 if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) {
767 error("kernel compression is bad\n");
768 return -1;
769 }
770#if NOTDEF
771 if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
772 return -1;
773 if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
774 return -1;
775#endif
776
777 uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
778 binary = buffer = malloc(uncompressed_size);
779
780 size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0],
781 OSSwapBigToHostInt32(kernel_header->compressed_size));
782 if (uncompressed_size != size) {
783 error("size mismatch from lzss: %x\n", size);
784 return -1;
785 }
786 if (OSSwapBigToHostInt32(kernel_header->adler32) !=
787 Adler32(binary, uncompressed_size)) {
788 printf("adler mismatch\n");
789 return -1;
790 }
791 }
792
793ret = ThinFatFile(&binary, &len);
794if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
795{
796archCpuType=CPU_TYPE_I386;
797ret = ThinFatFile(&binary, &len);
798}
799
800//patch_kernel(binary);
801
802ret = DecodeMachO(binary, rentry, raddr, rsize);
803
804if (ret<0 && archCpuType==CPU_TYPE_X86_64)
805{
806archCpuType=CPU_TYPE_I386;
807ret = DecodeMachO(binary, rentry, raddr, rsize);
808}
809
810
811return ret;
812}
813

Archive Download this file

Revision: 735