Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 577