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

Archive Download this file

Revision: 2826