Chameleon

Chameleon Svn Source Tree

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

Source at commit 583 created 10 years 3 months ago.
By meklort, Module updates, mostly bugfixes.
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
50static unsigned long Alder32( 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
76static unsigned long
77Alder32( 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
102return 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(alder32) !=
387 Alder32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
388 {
389 return -1;
390 }
391
392
393 // Make space for the MKext.
394 driversLength = GetPackageElement(length);
395 driversAddr = AllocateKernelMemory(driversLength);
396
397 // Copy the MKext.
398 memcpy((void *)driversAddr, (void *)package, driversLength);
399
400 // Add the MKext to the memory map.
401 sprintf(segName, "DriversPackage-%lx", driversAddr);
402 AllocateMemoryRange(segName, driversAddr, driversLength,
403 kBootDriverTypeMKEXT);
404
405 return 0;
406}
407
408//==========================================================================
409// LoadDriverPList
410
411long
412LoadDriverPList( char * dirSpec, char * name, long bundleType )
413{
414 long length, executablePathLength, bundlePathLength;
415 ModulePtr module;
416 TagPtr personalities;
417 char * buffer = 0;
418 char * tmpExecutablePath = 0;
419 char * tmpBundlePath = 0;
420 long ret = -1;
421
422 do {
423 // Save the driver path.
424
425 sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
426 (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
427 executablePathLength = strlen(gFileSpec) + 1;
428
429 tmpExecutablePath = malloc(executablePathLength);
430 if (tmpExecutablePath == 0) break;
431
432 strcpy(tmpExecutablePath, gFileSpec);
433
434 sprintf(gFileSpec, "%s/%s", dirSpec, name);
435 bundlePathLength = strlen(gFileSpec) + 1;
436
437 tmpBundlePath = malloc(bundlePathLength);
438 if (tmpBundlePath == 0) break;
439
440 strcpy(tmpBundlePath, gFileSpec);
441
442 // Construct the file spec to the plist, then load it.
443
444 sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
445 (bundleType == kCFBundleType2) ? "Contents/" : "");
446
447 length = LoadFile(gFileSpec);
448 if (length == -1) break;
449
450 length = length + 1;
451 buffer = malloc(length);
452 if (buffer == 0) break;
453
454 strlcpy(buffer, (char *)kLoadAddr, length);
455
456 // Parse the plist.
457
458 ret = ParseXML(buffer, &module, &personalities);
459 if (ret != 0) { break; }
460
461 // Allocate memory for the driver path and the plist.
462
463 module->executablePath = tmpExecutablePath;
464 module->bundlePath = tmpBundlePath;
465 module->bundlePathLength = bundlePathLength;
466 module->plistAddr = malloc(length);
467
468 if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
469 break;
470
471 // Save the driver path in the module.
472 //strcpy(module->driverPath, tmpDriverPath);
473 tmpExecutablePath = 0;
474 tmpBundlePath = 0;
475
476 // Add the plist to the module.
477
478 strlcpy(module->plistAddr, (char *)kLoadAddr, length);
479 module->plistLength = length;
480
481 // Add the module to the end of the module list.
482
483 if (gModuleHead == 0)
484 gModuleHead = module;
485 else
486 gModuleTail->nextModule = module;
487 gModuleTail = module;
488
489 // Add the persionalities to the personality list.
490
491 if (personalities) personalities = personalities->tag;
492 while (personalities != 0)
493 {
494 if (gPersonalityHead == 0)
495 gPersonalityHead = personalities->tag;
496 else
497 gPersonalityTail->tagNext = personalities->tag;
498
499 gPersonalityTail = personalities->tag;
500 personalities = personalities->tagNext;
501 }
502
503 ret = 0;
504 }
505 while (0);
506
507 if ( buffer ) free( buffer );
508 if ( tmpExecutablePath ) free( tmpExecutablePath );
509 if ( tmpBundlePath ) free( tmpBundlePath );
510
511 return ret;
512}
513
514
515//==========================================================================
516// LoadMatchedModules
517
518long LoadMatchedModules( void )
519{
520 TagPtr prop;
521 ModulePtr module;
522 char *fileName, segName[32];
523 DriverInfoPtr driver;
524 long length, driverAddr, driverLength;
525 void *executableAddr = 0;
526
527
528 module = gModuleHead;
529
530 while (module != 0)
531 {
532 if (module->willLoad)
533 {
534 prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
535
536 if (prop != 0)
537 {
538 fileName = prop->string;
539 sprintf(gFileSpec, "%s%s", module->executablePath, fileName);
540 length = LoadThinFatFile(gFileSpec, &executableAddr);
541if (length == 0)
542{
543length = LoadFile(gFileSpec);
544executableAddr = (void *)kLoadAddr;
545}
546 //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
547 }
548 else
549 length = 0;
550
551 if (length != -1)
552 {
553//driverModuleAddr = (void *)kLoadAddr;
554 //if (length != 0)
555 //{
556// ThinFatFile(&driverModuleAddr, &length);
557//}
558
559 // Make make in the image area.
560
561execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
562
563 driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
564 driverAddr = AllocateKernelMemory(driverLength);
565
566 // Set up the DriverInfo.
567 driver = (DriverInfoPtr)driverAddr;
568 driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
569 driver->plistLength = module->plistLength;
570 if (length != 0)
571 {
572 driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
573 module->plistLength);
574 driver->executableLength = length;
575 }
576 else
577 {
578 driver->executableAddr = 0;
579 driver->executableLength = 0;
580 }
581 driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
582 module->plistLength + driver->executableLength);
583 driver->bundlePathLength = module->bundlePathLength;
584
585 // Save the plist, module and bundle.
586 strcpy(driver->plistAddr, module->plistAddr);
587 if (length != 0)
588 {
589 memcpy(driver->executableAddr, executableAddr, length);
590 }
591 strcpy(driver->bundlePathAddr, module->bundlePath);
592
593 // Add an entry to the memory map.
594 sprintf(segName, "Driver-%lx", (unsigned long)driver);
595 AllocateMemoryRange(segName, driverAddr, driverLength,
596 kBootDriverTypeKEXT);
597 }
598 }
599 module = module->nextModule;
600 }
601
602 return 0;
603}
604
605//==========================================================================
606// MatchPersonalities
607
608long MatchPersonalities( void )
609{
610 /* IONameMatch support not implemented */
611 return 0;
612}
613
614//==========================================================================
615// MatchLibraries
616
617long MatchLibraries( void )
618{
619 TagPtr prop, prop2;
620 ModulePtr module, module2;
621 long done;
622
623 do {
624 done = 1;
625 module = gModuleHead;
626
627 while (module != 0)
628 {
629 if (module->willLoad == 1)
630 {
631 prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
632 if (prop != 0)
633 {
634 prop = prop->tag;
635 while (prop != 0)
636 {
637 module2 = gModuleHead;
638 while (module2 != 0)
639 {
640 prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
641 if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
642 {
643 if (module2->willLoad == 0) module2->willLoad = 1;
644 break;
645 }
646 module2 = module2->nextModule;
647 }
648 prop = prop->tagNext;
649 }
650 }
651 module->willLoad = 2;
652 done = 0;
653 }
654 module = module->nextModule;
655 }
656 }
657 while (!done);
658
659 return 0;
660}
661
662
663//==========================================================================
664// FindModule
665
666#if NOTDEF
667static ModulePtr
668FindModule( char * name )
669{
670 ModulePtr module;
671 TagPtr prop;
672
673 module = gModuleHead;
674
675 while (module != 0)
676 {
677 prop = GetProperty(module->dict, kPropCFBundleIdentifier);
678 if ((prop != 0) && !strcmp(name, prop->string)) break;
679 module = module->nextModule;
680 }
681
682 return module;
683}
684#endif /* NOTDEF */
685
686//==========================================================================
687// ParseXML
688
689static long
690ParseXML( char * buffer, ModulePtr * module, TagPtr * personalities )
691{
692long length, pos;
693TagPtr moduleDict, required;
694ModulePtr tmpModule;
695
696 pos = 0;
697
698 while (1)
699 {
700 length = XMLParseNextTag(buffer + pos, &moduleDict);
701 if (length == -1) break;
702
703 pos += length;
704
705 if (moduleDict == 0) continue;
706 if (moduleDict->type == kTagTypeDict) break;
707
708 XMLFreeTag(moduleDict);
709 }
710
711 if (length == -1) return -1;
712
713 required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
714 if ( (required == 0) ||
715(required->type != kTagTypeString) ||
716!strcmp(required->string, "Safe Boot"))
717 {
718 XMLFreeTag(moduleDict);
719 return -2;
720 }
721
722 tmpModule = malloc(sizeof(Module));
723 if (tmpModule == 0)
724 {
725 XMLFreeTag(moduleDict);
726 return -1;
727 }
728 tmpModule->dict = moduleDict;
729
730 // For now, load any module that has OSBundleRequired != "Safe Boot".
731
732 tmpModule->willLoad = 1;
733
734 *module = tmpModule;
735
736 // Get the personalities.
737
738 *personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
739
740 return 0;
741}
742
743#if NOTDEF
744static char gPlatformName[64];
745#endif
746
747long
748DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
749{
750 long ret;
751 compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary;
752 u_int32_t uncompressed_size, size;
753 void *buffer;
754unsigned long len;
755
756#if 0
757 printf("kernel header:\n");
758 printf("signature: 0x%x\n", kernel_header->signature);
759 printf("compress_type: 0x%x\n", kernel_header->compress_type);
760 printf("adler32: 0x%x\n", kernel_header->adler32);
761 printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
762 printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
763 getc();
764#endif
765
766 if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) {
767 if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) {
768 error("kernel compression is bad\n");
769 return -1;
770 }
771#if NOTDEF
772 if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
773 return -1;
774 if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
775 return -1;
776#endif
777
778 uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
779 binary = buffer = malloc(uncompressed_size);
780
781 size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0],
782 OSSwapBigToHostInt32(kernel_header->compressed_size));
783 if (uncompressed_size != size) {
784 error("size mismatch from lzss: %x\n", size);
785 return -1;
786 }
787 if (OSSwapBigToHostInt32(kernel_header->adler32) !=
788 Alder32(binary, uncompressed_size)) {
789 printf("adler mismatch\n");
790 return -1;
791 }
792 }
793
794ret = ThinFatFile(&binary, &len);
795if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
796{
797archCpuType=CPU_TYPE_I386;
798ret = ThinFatFile(&binary, &len);
799}
800
801//patch_kernel(binary);
802
803ret = DecodeMachO(binary, rentry, raddr, rsize);
804
805if (ret<0 && archCpuType==CPU_TYPE_X86_64)
806{
807archCpuType=CPU_TYPE_I386;
808ret = DecodeMachO(binary, rentry, raddr, rsize);
809}
810
811
812return ret;
813}
814

Archive Download this file

Revision: 583