Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2790