Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/i386/boot2/drivers.c

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 "modules.h"
42
43#if DEBUG
44#define DBG(x...)printf(x)
45#else
46#define DBG(x...)msglog(x)
47#endif
48
49// extern char gMacOSVersion[8];
50
51struct Module {
52struct Module *nextModule;
53long willLoad;
54TagPtr dict;
55char *plistAddr;
56long plistLength;
57char *executablePath;
58char *bundlePath;
59long bundlePathLength;
60};
61typedef struct Module Module, *ModulePtr;
62
63struct DriverInfo {
64char *plistAddr;
65long plistLength;
66void *executableAddr;
67long executableLength;
68void *bundlePathAddr;
69long bundlePathLength;
70};
71typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
72
73#define kDriverPackageSignature1 'MKXT'
74#define kDriverPackageSignature2 'MOSX'
75
76struct DriversPackage {
77unsigned long signature1;
78unsigned long signature2;
79unsigned long length;
80unsigned long adler32;
81unsigned long version;
82unsigned long numDrivers;
83unsigned long reserved1;
84unsigned long reserved2;
85};
86typedef struct DriversPackage DriversPackage;
87
88enum {
89kCFBundleType2,
90kCFBundleType3
91};
92
93long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
94
95/*static*/ unsigned long Adler32( unsigned char * buffer, long length );
96
97long FileLoadDrivers(char *dirSpec, long plugin);
98long NetLoadDrivers(char *dirSpec);
99long LoadDriverMKext(char *fileSpec);
100long LoadDriverPList(char *dirSpec, char *name, long bundleType);
101long LoadMatchedModules(void);
102
103static long MatchPersonalities(void);
104static long MatchLibraries(void);
105#ifdef NOTDEF
106static ModulePtr FindModule(char *name);
107static void ThinFatFile(void **loadAddrP, unsigned long *lengthP);
108#endif
109static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities);
110static long InitDriverSupport(void);
111
112ModulePtr gModuleHead, gModuleTail;
113static TagPtrgPersonalityHead, gPersonalityTail;
114static char*gExtensionsSpec;
115static char*gDriverSpec;
116static char*gFileSpec;
117static char*gTempSpec;
118static char*gFileName;
119// Bungo:
120char gDarwinBuildVerStr[256] = "Darwin Kernel Version";
121
122/*static*/ unsigned long Adler32( unsigned char *buffer, long length )
123{
124long cnt;
125unsigned long result, lowHalf, highHalf;
126
127lowHalf = 1;
128highHalf = 0;
129
130for (cnt = 0; cnt < length; cnt++)
131{
132if ((cnt % 5000) == 0)
133{
134lowHalf %= 65521L;
135highHalf %= 65521L;
136}
137
138lowHalf += buffer[cnt];
139highHalf += lowHalf;
140}
141
142lowHalf %= 65521L;
143highHalf %= 65521L;
144
145result = (highHalf << 16) | lowHalf;
146
147return result;
148}
149
150//==========================================================================
151// InitDriverSupport
152static long InitDriverSupport( void )
153{
154gExtensionsSpec = malloc( 4096 );
155gDriverSpec = malloc( 4096 );
156gFileSpec = malloc( 4096 );
157gTempSpec = malloc( 4096 );
158gFileName = malloc( 4096 );
159
160if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
161{
162stop("InitDriverSupport error");
163}
164
165return 0;
166}
167
168//==========================================================================
169// LoadDrivers
170long LoadDrivers( char *dirSpec )
171{
172char dirSpecExtra[1024];
173
174if ( InitDriverSupport() != 0 )
175{
176return 0;
177}
178
179// Load extra drivers if a hook has been installed.
180if (LoadExtraDrivers_p != NULL)
181{
182(*LoadExtraDrivers_p)(&FileLoadDrivers);
183}
184
185if ( gBootFileType == kNetworkDeviceType )
186{
187if (NetLoadDrivers(dirSpec) != 0)
188{
189error("LoadDrivers: Could not load drivers from the network\n");
190return -1;
191}
192}
193else if ( gBootFileType == kBlockDeviceType )
194{
195// First try to load Extra extensions from the ramdisk if isn't aliased as bt(0,0).
196if (gRAMDiskVolume && !gRAMDiskBTAliased)
197{
198strcpy(dirSpecExtra, "rd(0,0)/Extra/");
199FileLoadDrivers(dirSpecExtra, 0);
200}
201
202// Next try to load Extra extensions from the selected root partition.
203strlcpy(dirSpecExtra, "/Extra/", sizeof(dirSpecExtra));
204if (FileLoadDrivers(dirSpecExtra, 0) != 0)
205{
206// If failed, then try to load Extra extensions from the boot partition
207// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
208if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
209|| (gRAMDiskVolume && gRAMDiskBTAliased) )
210{
211// Next try a specfic OS version folder ie 10.5
212sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion[0]);
213if (FileLoadDrivers(dirSpecExtra, 0) != 0) {
214// Next we'll try the base
215strlcpy(dirSpecExtra, "bt(0,0)/Extra/", sizeof(dirSpecExtra));
216FileLoadDrivers(dirSpecExtra, 0);
217}
218}
219}
220if(!gHaveKernelCache)
221{
222// Don't load main driver (from /System/Library/Extentions) if gHaveKernelCache is set.
223// since these drivers will already be in the kernel cache.
224// NOTE: when gHaveKernelCache, xnu cannot (by default) load *any* extra kexts from the bootloader.
225// The /Extra code is not disabled in this case due to a kernel patch that allows for this to happen.
226
227// Also try to load Extensions from boot helper partitions.
228if (gBootVolume->flags & kBVFlagBooter)
229{
230strlcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/", sizeof(dirSpecExtra));
231if (FileLoadDrivers(dirSpecExtra, 0) != 0)
232{
233strlcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/", sizeof(dirSpecExtra));
234if (FileLoadDrivers(dirSpecExtra, 0) != 0)
235{
236strlcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/", sizeof(dirSpecExtra));
237FileLoadDrivers(dirSpecExtra, 0);
238}
239}
240}
241
242if (gMKextName[0] != '\0')
243{
244verbose("LoadDrivers: Loading from '%s'\n", gMKextName);
245if ( LoadDriverMKext(gMKextName) != 0 )
246{
247error("Could not load %s\n", gMKextName);
248return -1;
249}
250}
251else
252{
253verbose("Attempting to loading drivers from standard repositories:\n");
254
255if ( (gMacOSVersion[3] == '9') || ((gMacOSVersion[3] == '1') && ((gMacOSVersion[4] == '0') || gMacOSVersion[4] == '1' ) )) // issue 352
256{
257verbose("\t- Third party extensions search path: /Library/Extensions\n");
258strlcpy(gExtensionsSpec, dirSpec, 4087); /* 4096 - sizeof("Library/") mean 4096 - 9 = 4087 */
259strcat(gExtensionsSpec, "Library/");
260FileLoadDrivers(gExtensionsSpec, 0);
261}
262
263verbose("\t- Apple extensions search path: /System/Library/Extensions\n");
264strlcpy(gExtensionsSpec, dirSpec, 4080); /* 4096 - sizeof("System/Library/") mean 4096 -16 = 4080 */
265strcat(gExtensionsSpec, "System/Library/");
266FileLoadDrivers(gExtensionsSpec, 0);
267}
268
269}
270}
271else
272{
273return 0;
274}
275
276MatchPersonalities();
277
278MatchLibraries();
279
280LoadMatchedModules();
281
282return 0;
283}
284
285//==========================================================================
286// FileLoadMKext
287static long FileLoadMKext( const char *dirSpec, const char *extDirSpec )
288{
289longret, flags;
290u_int32_ttime, time2;
291charaltDirSpec[512];
292
293snprintf(altDirSpec, sizeof(altDirSpec), "%s%s", dirSpec, extDirSpec);
294ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
295
296if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
297{
298ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
299
300if ((ret != 0)
301|| ((flags & kFileTypeMask) != kFileTypeDirectory)
302|| (((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
303{
304snprintf(gDriverSpec, sizeof(altDirSpec) + 18, "%sExtensions.mkext", altDirSpec);
305verbose("LoadDrivers: Loading from '%s'\n", gDriverSpec);
306
307if (LoadDriverMKext(gDriverSpec) == 0)
308{
309return 0;
310}
311}
312}
313return -1;
314}
315
316//==========================================================================
317// FileLoadDrivers
318long FileLoadDrivers( char *dirSpec, long plugin )
319{
320long longindex;
321longret, length, flags, bundleType;
322longresult = -1;
323u_int32_ttime;
324const char* name;
325
326if ( !plugin )
327{
328// First try 10.6's path for loading Extensions.mkext.
329if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0) {
330return 0;
331}
332
333// Next try the legacy path.
334else if (FileLoadMKext(dirSpec, "") == 0)
335{
336return 0;
337}
338
339strcat(dirSpec, "Extensions");
340}
341
342index = 0;
343while (1)
344{
345ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
346if (ret == -1) {
347break;
348}
349
350// Make sure this is a directory.
351if ((flags & kFileTypeMask) != kFileTypeDirectory)
352{
353continue;
354}
355
356// Make sure this is a kext.
357length = strlen(name);
358if (strncmp(name + length - 5, ".kext", sizeof(".kext") ))
359{
360continue;
361}
362
363// Save the file name.
364strlcpy(gFileName, name, 4096);
365
366// Determine the bundle type.
367snprintf(gTempSpec, 4096, "%s/%s", dirSpec, gFileName);
368ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
369if (ret == 0)
370{
371bundleType = kCFBundleType2;
372}
373else
374{
375bundleType = kCFBundleType3;
376}
377
378if (!plugin)
379{
380snprintf(gDriverSpec, 4096, "%s/%s/%sPlugIns", dirSpec, gFileName, (bundleType == kCFBundleType2) ? "Contents/" : "");
381}
382
383ret = LoadDriverPList(dirSpec, gFileName, bundleType);
384
385if (result != 0)
386{
387result = ret;
388}
389
390if (!plugin)
391{
392FileLoadDrivers(gDriverSpec, 1);
393}
394}
395
396return result;
397}
398
399//==========================================================================
400//
401long NetLoadDrivers( char *dirSpec )
402{
403long tries;
404
405#if NODEF
406long cnt;
407
408// Get the name of the kernel
409cnt = strlen(gBootFile);
410while (cnt--) {
411if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ','))
412{
413cnt++;
414break;
415}
416}
417#endif
418
419// INTEL modification
420snprintf(gDriverSpec, 4096, "%s%s.mkext", dirSpec, bootInfo->bootFile);
421
422verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
423
424tries = 3;
425while (tries--)
426{
427if (LoadDriverMKext(gDriverSpec) == 0)
428{
429break;
430}
431}
432if (tries == -1)
433{
434return -1;
435}
436
437return 0;
438}
439
440//==========================================================================
441// loadDriverMKext
442long LoadDriverMKext( char *fileSpec )
443{
444unsigned longdriversAddr, driversLength;
445longlength;
446charsegName[32];
447DriversPackage*package;
448
449#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
450
451// Load the MKext.
452length = LoadThinFatFile(fileSpec, (void **)&package);
453if (length < sizeof (DriversPackage))
454{
455return -1;
456}
457
458// call hook to notify modules that the mkext has been loaded
459execute_hook("LoadDriverMKext", (void *)fileSpec, (void *)package, (void *) &length, NULL);
460
461
462// Verify the MKext.
463if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
464( GetPackageElement(signature2) != kDriverPackageSignature2) ||
465( GetPackageElement(length) > kLoadSize ) ||
466( GetPackageElement(adler32) !=
467Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
468{
469return -1;
470}
471
472// Make space for the MKext.
473driversLength = GetPackageElement(length);
474driversAddr = AllocateKernelMemory(driversLength);
475
476// Copy the MKext.
477memcpy((void *)driversAddr, (void *)package, driversLength);
478
479// Add the MKext to the memory map.
480snprintf(segName, sizeof(segName), "DriversPackage-%lx", driversAddr);
481AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT);
482
483return 0;
484}
485
486//==========================================================================
487// LoadDriverPList
488long LoadDriverPList( char *dirSpec, char *name, long bundleType )
489{
490long length, executablePathLength, bundlePathLength;
491ModulePtr module;
492TagPtr personalities;
493char * buffer = 0;
494char * tmpExecutablePath = 0;
495char * tmpBundlePath = 0;
496long ret = -1;
497
498do{
499// Save the driver path.
500
501if(name)
502{
503snprintf(gFileSpec, 4096, "%s/%s/%s", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
504}
505else
506{
507snprintf(gFileSpec, 4096, "%s/%s", dirSpec, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
508}
509executablePathLength = strlen(gFileSpec) + 1;
510
511tmpExecutablePath = malloc(executablePathLength);
512if (tmpExecutablePath == 0) {
513break;
514}
515strlcpy(tmpExecutablePath, gFileSpec, executablePathLength);
516
517if(name)
518{
519snprintf(gFileSpec, 4096, "%s/%s", dirSpec, name);
520}
521else
522{
523strncpy(gFileSpec, dirSpec, 4096);
524}
525bundlePathLength = strlen(gFileSpec) + 1;
526
527tmpBundlePath = malloc(bundlePathLength);
528if (tmpBundlePath == 0)
529{
530break;
531}
532
533strlcpy(tmpBundlePath, gFileSpec, bundlePathLength);
534
535// Construct the file spec to the plist, then load it.
536
537if(name)
538{
539snprintf(gFileSpec, 4096, "%s/%s/%sInfo.plist", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/" : "");
540}
541else
542{
543snprintf(gFileSpec, 4096, "%s/%sInfo.plist", dirSpec, (bundleType == kCFBundleType2) ? "Contents/" : "");
544}
545
546length = LoadFile(gFileSpec);
547
548if (length == -1)
549{
550break;
551}
552
553length = length + 1;
554buffer = malloc(length);
555
556if (buffer == 0)
557{
558break;
559}
560
561strlcpy(buffer, (char *)kLoadAddr, length);
562
563// Parse the plist.
564
565ret = ParseXML(buffer, &module, &personalities);
566
567if (ret != 0) {
568break;
569}
570
571if (!module) // cparm
572{
573ret = -1;
574break;
575} // Should never happen but it will make the compiler happy
576
577// Allocate memory for the driver path and the plist.
578
579module->executablePath = tmpExecutablePath;
580module->bundlePath = tmpBundlePath;
581module->bundlePathLength = bundlePathLength;
582module->plistAddr = malloc(length);
583
584if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
585{
586break;
587}
588
589// Save the driver path in the module.
590//strcpy(module->driverPath, tmpDriverPath);
591tmpExecutablePath = 0;
592tmpBundlePath = 0;
593
594// Add the plist to the module.
595
596strlcpy(module->plistAddr, (char *)kLoadAddr, length);
597module->plistLength = length;
598
599// Add the module to the end of the module list.
600
601if (gModuleHead == 0) {
602gModuleHead = module;
603} else {
604gModuleTail->nextModule = module;
605}
606gModuleTail = module;
607
608// Add the persionalities to the personality list.
609
610if (personalities) {
611personalities = personalities->tag;
612}
613while (personalities != 0)
614{
615if (gPersonalityHead == 0) {
616gPersonalityHead = personalities->tag;
617} else {
618gPersonalityTail->tagNext = personalities->tag;
619}
620
621gPersonalityTail = personalities->tag;
622personalities = personalities->tagNext;
623}
624
625ret = 0;
626}
627while (0);
628
629if ( buffer ) {
630free( buffer );
631}
632if ( tmpExecutablePath ) {
633free( tmpExecutablePath );
634}
635if ( tmpBundlePath ) {
636free( tmpBundlePath );
637}
638return ret;
639}
640
641//==========================================================================
642// LoadMatchedModules
643long LoadMatchedModules( void )
644{
645TagPtr prop;
646ModulePtr module;
647char *fileName, segName[32];
648DriverInfoPtr driver;
649long length, driverAddr, driverLength;
650void *executableAddr = 0;
651
652module = gModuleHead;
653
654while (module != 0)
655{
656if (module->willLoad)
657{
658prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
659
660if (prop != 0)
661{
662fileName = prop->string;
663snprintf(gFileSpec, 4096, "%s%s", module->executablePath, fileName);
664
665length = LoadThinFatFile(gFileSpec, &executableAddr);
666if (length == 0)
667{
668length = LoadFile(gFileSpec);
669executableAddr = (void *)kLoadAddr;
670}
671//printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getchar();
672}
673else
674{
675length = 0;
676}
677
678if ((length != -1) && executableAddr)
679{
680//driverModuleAddr = (void *)kLoadAddr;
681//if (length != 0)
682//{
683//ThinFatFile(&driverModuleAddr, &length);
684//}
685
686// Make make in the image area.
687
688execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
689
690driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
691driverAddr = AllocateKernelMemory(driverLength);
692
693// Set up the DriverInfo.
694driver = (DriverInfoPtr)driverAddr;
695driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
696driver->plistLength = module->plistLength;
697
698if (length != 0)
699{
700driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
701 module->plistLength);
702driver->executableLength = length;
703}
704else
705{
706driver->executableAddr = 0;
707driver->executableLength = 0;
708}
709
710driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
711 module->plistLength + driver->executableLength);
712driver->bundlePathLength = module->bundlePathLength;
713
714// Save the plist, module and bundle.
715strlcpy(driver->plistAddr, module->plistAddr, driver->plistLength);
716
717if (length != 0)
718{
719memcpy(driver->executableAddr, executableAddr, length);
720}
721
722strlcpy(driver->bundlePathAddr, module->bundlePath, module->bundlePathLength);
723
724// Add an entry to the memory map.
725snprintf(segName, sizeof(segName), "Driver-%lx", (unsigned long)driver);
726AllocateMemoryRange(segName, driverAddr, driverLength,
727kBootDriverTypeKEXT);
728}
729}
730module = module->nextModule;
731}
732
733return 0;
734}
735
736//==========================================================================
737// MatchPersonalities
738static long MatchPersonalities( void )
739{
740/* IONameMatch support not implemented */
741return 0;
742}
743
744//==========================================================================
745// MatchLibraries
746static long MatchLibraries( void )
747{
748TagPtr prop;
749TagPtr prop2;
750ModulePtr module;
751ModulePtr module2;
752long done;
753
754do {
755done = 1;
756module = gModuleHead;
757
758while (module != 0)
759{
760if (module->willLoad == 1)
761{
762prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
763
764if (prop != 0)
765{
766prop = prop->tag;
767
768while (prop != 0)
769{
770module2 = gModuleHead;
771
772while (module2 != 0)
773{
774prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
775
776if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
777{
778if (module2->willLoad == 0)
779{
780module2->willLoad = 1;
781}
782break;
783}
784module2 = module2->nextModule;
785}
786prop = prop->tagNext;
787}
788}
789module->willLoad = 2;
790done = 0;
791}
792module = module->nextModule;
793}
794}
795while (!done);
796
797return 0;
798}
799
800//==========================================================================
801// FindModule
802
803#if NOTDEF
804static ModulePtr FindModule( char *name )
805{
806ModulePtr module;
807TagPtr prop;
808
809module = gModuleHead;
810
811while (module != 0)
812{
813prop = GetProperty(module->dict, kPropCFBundleIdentifier);
814
815if ((prop != 0) && !strcmp(name, prop->string))
816{
817break;
818}
819
820module = module->nextModule;
821}
822
823return module;
824}
825#endif /* NOTDEF */
826
827//==========================================================================
828// ParseXML
829static long ParseXML( char *buffer, ModulePtr *module, TagPtr *personalities )
830{
831longlength;
832longpos = 0;
833TagPtrmoduleDict;
834TagPtrrequired;
835ModulePtrtmpModule;
836
837while (1)
838{
839length = XMLParseNextTag(buffer + pos, &moduleDict);
840if (length == -1)
841{
842break;
843}
844
845pos += length;
846
847if (moduleDict == 0)
848{
849continue;
850}
851if (moduleDict->type == kTagTypeDict)
852{
853break;
854}
855XMLFreeTag(moduleDict);
856}
857
858if (length == -1)
859{
860return -1;
861}
862
863required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
864
865if ( (required == 0) || (required->type != kTagTypeString) || !strncmp(required->string, "Safe Boot", sizeof("Safe Boot")))
866{
867XMLFreeTag(moduleDict);
868return -2;
869}
870
871tmpModule = malloc(sizeof(Module));
872if (tmpModule == 0)
873{
874XMLFreeTag(moduleDict);
875return -1;
876}
877tmpModule->dict = moduleDict;
878
879// For now, load any module that has OSBundleRequired != "Safe Boot".
880
881tmpModule->willLoad = 1;
882
883*module = tmpModule;
884
885// Get the personalities.
886
887*personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
888
889return 0;
890}
891
892#if NOTDEF
893static char gPlatformName[64];
894#endif
895
896long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
897{
898long ret = 0;
899compressed_kernel_header *kernel_header = (compressed_kernel_header *)binary;
900u_int32_t uncompressed_size = 0, size = 0, adler32 = 0;
901void *buffer = NULL;
902unsigned long len = 0;
903
904/*#if 0
905printf("kernel header:\n");
906printf("signature: 0x%x\n", kernel_header->signature);
907printf("compress_type: 0x%x\n", kernel_header->compress_type);
908printf("adler32: 0x%x\n", kernel_header->adler32);
909printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
910printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
911getchar();
912#endif*/
913
914if (kernel_header->signature == OSSwapBigToHostConstInt32('comp'))
915{
916DBG("Decompressing Kernel Cache:\n");
917
918if ((kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) &&
919(kernel_header->compress_type != OSSwapBigToHostConstInt32('lzvn')))
920{
921error("\tERROR: kernel compression is bad!\n");
922return -1;
923}
924
925if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
926{
927verbose ("\t- Decompressing Kernel Using lzss\n");
928}
929
930if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
931{
932verbose ("\t- Decompressing Kernel Using lzvn\n");
933}
934
935#if NOTDEF
936if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
937{
938return -1;
939}
940
941if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
942{
943return -1;
944}
945#endif
946uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
947binary = buffer = malloc(uncompressed_size);
948
949// MinusZwei
950size = 0;
951switch (kernel_header->compress_type)
952{
953case OSSwapBigToHostConstInt32('lzvn'):
954size = lzvn_decode(binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
955break;
956
957case OSSwapBigToHostConstInt32('lzss'):
958size = decompress_lzss((u_int8_t *)binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
959break;
960
961default:
962break;
963}
964// MinusZwei
965
966if (uncompressed_size != size)
967{
968if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
969{
970error("ERROR! Size mismatch from lzvn (found: %x, expected: %x).\n", size, uncompressed_size);
971}
972
973if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
974{
975error("ERROR! size mismatch from lzss (found: %x, expected: %x).\n", size, uncompressed_size);
976}
977
978return -1;
979}
980
981adler32 = Adler32(binary, uncompressed_size);
982if (OSSwapBigToHostInt32(kernel_header->adler32) != adler32)
983{
984error("ERROR! Adler mismatch (found: %X, expected: %X).\n", adler32, OSSwapBigToHostInt32(kernel_header->adler32));
985return -1;
986}
987
988DBG("\n");
989}
990
991ret = ThinFatFile(&binary, &len);
992if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
993{
994archCpuType=CPU_TYPE_I386;
995ret = ThinFatFile(&binary, &len);
996}
997
998// Bungo: scan binary for Darwin Kernel Version string
999uint32_t offset = 0;
1000strncpy(gDarwinBuildVerStr, "Darwin Kernel Version", sizeof(gDarwinBuildVerStr));
1001
1002while ((offset < 0xFFFFFFFF - (uint32_t)binary - 256) && memcmp(binary + offset, gDarwinBuildVerStr, 21))
1003{
1004offset++;
1005}
1006if (offset < 0xFFFFFFFF - (uint32_t)binary - 256)
1007{
1008strncpy(gDarwinBuildVerStr, (char *)(binary + offset), sizeof(gDarwinBuildVerStr));
1009}
1010else
1011{
1012strcat(gDarwinBuildVerStr, ": Unknown");
1013}
1014
1015// Notify modules that the kernel has been decompressed, thinned and is about to be decoded
1016execute_hook("DecodeKernel", (void *)binary, NULL, NULL, NULL);
1017
1018/* ================================================================ */
1019
1020// Entry point
1021
1022/* ================================================================ */
1023
1024ret = DecodeMachO(binary, rentry, raddr, rsize);
1025if (ret < 0 && archCpuType == CPU_TYPE_X86_64)
1026{
1027archCpuType = CPU_TYPE_I386;
1028ret = DecodeMachO(binary, rentry, raddr, rsize);
1029}
1030
1031return ret;
1032}
1033

Archive Download this file

Revision: 2769