Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 575