Chameleon

Chameleon Svn Source Tree

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

Source at commit 561 created 13 years 7 months ago.
By meklort, Added missing gma files
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
52static long FileLoadDrivers(char *dirSpec, long plugin);
53#ifndef OPTION_ROM
54static long NetLoadDrivers(char *dirSpec);
55#endif
56static long LoadDriverMKext(char *fileSpec);
57static long LoadDriverPList(char *dirSpec, char *name, long bundleType);
58static long LoadMatchedModules(void);
59static long MatchPersonalities(void);
60static long 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);
66static long InitDriverSupport(void);
67
68static ModulePtr gModuleHead, gModuleTail;
69static TagPtr gPersonalityHead, gPersonalityTail;
70static char * gExtensionsSpec;
71static char * gDriverSpec;
72static char * gFileSpec;
73static char * gTempSpec;
74static char * 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
109static long
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
154if (gRAMDiskVolume && !gRAMDiskBTAliased)
155{
156strcpy(dirSpecExtra, "rd(0,0)/Extra/");
157FileLoadDrivers(dirSpecExtra, 0);
158}
159#endif
160// Next try to load Extra extensions from the selected root partition.
161strcpy(dirSpecExtra, "/Extra/");
162if (FileLoadDrivers(dirSpecExtra, 0) != 0)
163{
164// If failed, then try to load Extra extensions from the boot partition
165// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
166if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
167#ifndef OPTION_ROM
168|| (gRAMDiskVolume && gRAMDiskBTAliased) )
169#else
170)
171#endif
172{
173// First try a specfic OS version folder ie 10.5
174sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion);
175if (FileLoadDrivers(dirSpecExtra, 0) != 0)
176{
177// Next we'll try the base
178strcpy(dirSpecExtra, "bt(0,0)/Extra/");
179FileLoadDrivers(dirSpecExtra, 0);
180}
181}
182}
183
184// TODO: fix this, the order does matter, and it's not correct now.
185// Also try to load Extensions from boot helper partitions.
186if (gBootVolume->flags & kBVFlagBooter)
187{
188strcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/");
189if (FileLoadDrivers(dirSpecExtra, 0) != 0)
190{
191strcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/");
192if (FileLoadDrivers(dirSpecExtra, 0) != 0)
193{
194strcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/");
195FileLoadDrivers(dirSpecExtra, 0);
196}
197}
198}
199
200if (gMKextName[0] != '\0')
201{
202verbose("LoadDrivers: Loading from [%s]\n", gMKextName);
203if ( LoadDriverMKext(gMKextName) != 0 )
204{
205error("Could not load %s\n", gMKextName);
206return -1;
207}
208}
209else
210{
211strcpy(gExtensionsSpec, dirSpec);
212strcat(gExtensionsSpec, "System/Library/");
213FileLoadDrivers(gExtensionsSpec, 0);
214}
215}
216else
217{
218return 0;
219}
220
221 MatchPersonalities();
222
223 MatchLibraries();
224
225 LoadMatchedModules();
226
227 return 0;
228}
229
230//==========================================================================
231// FileLoadMKext
232
233static long
234FileLoadMKext( const char * dirSpec, const char * extDirSpec )
235{
236long ret, flags, time, time2;
237char altDirSpec[512];
238
239sprintf (altDirSpec, "%s%s", dirSpec, extDirSpec);
240ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
241if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
242{
243ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
244if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeDirectory) ||
245(((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
246{
247sprintf(gDriverSpec, "%sExtensions.mkext", altDirSpec);
248verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec);
249if (LoadDriverMKext(gDriverSpec) == 0) return 0;
250}
251}
252return -1;
253}
254
255//==========================================================================
256// FileLoadDrivers
257
258static long
259FileLoadDrivers( char * dirSpec, long plugin )
260{
261 long ret, length, flags, time, bundleType;
262 long long index;
263 long result = -1;
264 const char * name;
265
266 if ( !plugin )
267 {
268 // First try 10.6's path for loading Extensions.mkext.
269 if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0)
270return 0;
271
272 // Next try the legacy path.
273 else if (FileLoadMKext(dirSpec, "") == 0)
274return 0;
275
276 strcat(dirSpec, "Extensions");
277 }
278
279 index = 0;
280 while (1) {
281 ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
282 if (ret == -1) break;
283
284 // Make sure this is a directory.
285 if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
286
287 // Make sure this is a kext.
288 length = strlen(name);
289 if (strcmp(name + length - 5, ".kext")) continue;
290
291 // Save the file name.
292 strcpy(gFileName, name);
293
294 // Determine the bundle type.
295 sprintf(gTempSpec, "%s/%s", dirSpec, gFileName);
296 ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
297 if (ret == 0) bundleType = kCFBundleType2;
298 else bundleType = kCFBundleType3;
299
300 if (!plugin)
301 sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName,
302 (bundleType == kCFBundleType2) ? "Contents/" : "");
303
304 ret = LoadDriverPList(dirSpec, gFileName, bundleType);
305
306 if (result != 0)
307result = ret;
308
309 if (!plugin)
310FileLoadDrivers(gDriverSpec, 1);
311 }
312
313 return result;
314}
315
316//==========================================================================
317//
318#ifndef OPTION_ROM
319static long
320NetLoadDrivers( char * dirSpec )
321{
322 long tries;
323
324#if NODEF
325 long cnt;
326
327 // Get the name of the kernel
328 cnt = strlen(gBootFile);
329 while (cnt--) {
330 if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ',')) {
331cnt++;
332break;
333 }
334 }
335#endif
336
337 // INTEL modification
338 sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile);
339
340 verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
341
342 tries = 3;
343 while (tries--)
344 {
345 if (LoadDriverMKext(gDriverSpec) == 0) break;
346 }
347 if (tries == -1) return -1;
348
349 return 0;
350}
351#endif
352//==========================================================================
353// loadDriverMKext
354
355static long
356LoadDriverMKext( char * fileSpec )
357{
358 unsigned long driversAddr, driversLength;
359 long length;
360 char segName[32];
361 DriversPackage * package;
362
363#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
364
365 // Load the MKext.
366 length = LoadThinFatFile(fileSpec, (void **)&package);
367 if (length < sizeof (DriversPackage)) return -1;
368
369// call hook to notify modules that the mkext has been loaded
370execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) length, NULL);
371
372
373 // Verify the MKext.
374 if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
375 ( GetPackageElement(signature2) != kDriverPackageSignature2) ||
376 ( GetPackageElement(length) > kLoadSize ) ||
377 ( GetPackageElement(alder32) !=
378 Alder32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
379 {
380 return -1;
381 }
382
383
384 // Make space for the MKext.
385 driversLength = GetPackageElement(length);
386 driversAddr = AllocateKernelMemory(driversLength);
387
388 // Copy the MKext.
389 memcpy((void *)driversAddr, (void *)package, driversLength);
390
391 // Add the MKext to the memory map.
392 sprintf(segName, "DriversPackage-%lx", driversAddr);
393 AllocateMemoryRange(segName, driversAddr, driversLength,
394 kBootDriverTypeMKEXT);
395
396 return 0;
397}
398
399//==========================================================================
400// LoadDriverPList
401
402static long
403LoadDriverPList( char * dirSpec, char * name, long bundleType )
404{
405 long length, executablePathLength, bundlePathLength;
406 ModulePtr module;
407 TagPtr personalities;
408 char * buffer = 0;
409 char * tmpExecutablePath = 0;
410 char * tmpBundlePath = 0;
411 long ret = -1;
412
413 do {
414 // Save the driver path.
415
416 sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
417 (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
418 executablePathLength = strlen(gFileSpec) + 1;
419
420 tmpExecutablePath = malloc(executablePathLength);
421 if (tmpExecutablePath == 0) break;
422
423 strcpy(tmpExecutablePath, gFileSpec);
424
425 sprintf(gFileSpec, "%s/%s", dirSpec, name);
426 bundlePathLength = strlen(gFileSpec) + 1;
427
428 tmpBundlePath = malloc(bundlePathLength);
429 if (tmpBundlePath == 0) break;
430
431 strcpy(tmpBundlePath, gFileSpec);
432
433 // Construct the file spec to the plist, then load it.
434
435 sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
436 (bundleType == kCFBundleType2) ? "Contents/" : "");
437
438 length = LoadFile(gFileSpec);
439 if (length == -1) break;
440
441 length = length + 1;
442 buffer = malloc(length);
443 if (buffer == 0) break;
444
445 strlcpy(buffer, (char *)kLoadAddr, length);
446
447 // Parse the plist.
448
449 ret = ParseXML(buffer, &module, &personalities);
450 if (ret != 0) { break; }
451
452 // Allocate memory for the driver path and the plist.
453
454 module->executablePath = tmpExecutablePath;
455 module->bundlePath = tmpBundlePath;
456 module->bundlePathLength = bundlePathLength;
457 module->plistAddr = malloc(length);
458
459 if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
460 break;
461
462 // Save the driver path in the module.
463 //strcpy(module->driverPath, tmpDriverPath);
464 tmpExecutablePath = 0;
465 tmpBundlePath = 0;
466
467 // Add the plist to the module.
468
469 strlcpy(module->plistAddr, (char *)kLoadAddr, length);
470 module->plistLength = length;
471
472 // Add the module to the end of the module list.
473
474 if (gModuleHead == 0)
475 gModuleHead = module;
476 else
477 gModuleTail->nextModule = module;
478 gModuleTail = module;
479
480 // Add the persionalities to the personality list.
481
482 if (personalities) personalities = personalities->tag;
483 while (personalities != 0)
484 {
485 if (gPersonalityHead == 0)
486 gPersonalityHead = personalities->tag;
487 else
488 gPersonalityTail->tagNext = personalities->tag;
489
490 gPersonalityTail = personalities->tag;
491 personalities = personalities->tagNext;
492 }
493
494 ret = 0;
495 }
496 while (0);
497
498 if ( buffer ) free( buffer );
499 if ( tmpExecutablePath ) free( tmpExecutablePath );
500 if ( tmpBundlePath ) free( tmpBundlePath );
501
502 return ret;
503}
504
505
506//==========================================================================
507// LoadMatchedModules
508
509static long
510LoadMatchedModules( void )
511{
512 TagPtr prop;
513 ModulePtr module;
514 char *fileName, segName[32];
515 DriverInfoPtr driver;
516 long length, driverAddr, driverLength;
517 void *executableAddr = 0;
518
519
520 module = gModuleHead;
521
522 while (module != 0)
523 {
524 if (module->willLoad)
525 {
526 prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
527
528 if (prop != 0)
529 {
530 fileName = prop->string;
531 sprintf(gFileSpec, "%s%s", module->executablePath, fileName);
532 length = LoadThinFatFile(gFileSpec, &executableAddr);
533if (length == 0)
534{
535length = LoadFile(gFileSpec);
536executableAddr = (void *)kLoadAddr;
537}
538 //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
539 }
540 else
541 length = 0;
542
543 if (length != -1)
544 {
545//driverModuleAddr = (void *)kLoadAddr;
546 //if (length != 0)
547 //{
548// ThinFatFile(&driverModuleAddr, &length);
549//}
550
551 // Make make in the image area.
552
553execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
554
555 driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
556 driverAddr = AllocateKernelMemory(driverLength);
557
558 // Set up the DriverInfo.
559 driver = (DriverInfoPtr)driverAddr;
560 driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
561 driver->plistLength = module->plistLength;
562 if (length != 0)
563 {
564 driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
565 module->plistLength);
566 driver->executableLength = length;
567 }
568 else
569 {
570 driver->executableAddr = 0;
571 driver->executableLength = 0;
572 }
573 driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
574 module->plistLength + driver->executableLength);
575 driver->bundlePathLength = module->bundlePathLength;
576
577 // Save the plist, module and bundle.
578 strcpy(driver->plistAddr, module->plistAddr);
579 if (length != 0)
580 {
581 memcpy(driver->executableAddr, executableAddr, length);
582 }
583 strcpy(driver->bundlePathAddr, module->bundlePath);
584
585 // Add an entry to the memory map.
586 sprintf(segName, "Driver-%lx", (unsigned long)driver);
587 AllocateMemoryRange(segName, driverAddr, driverLength,
588 kBootDriverTypeKEXT);
589 }
590 }
591 module = module->nextModule;
592 }
593
594 return 0;
595}
596
597//==========================================================================
598// MatchPersonalities
599
600static long
601MatchPersonalities( void )
602{
603 /* IONameMatch support not implemented */
604 return 0;
605}
606
607//==========================================================================
608// MatchLibraries
609
610static long
611MatchLibraries( 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: 561