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
95static inline 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
122static inline 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// Firstly try to load drivers from Common folder
207sprintf(dirSpecExtra, "bt(0,0)/Extra/Common/");
208FileLoadDrivers(dirSpecExtra, 0);
209// =====================================================================
210
211// Next try to load Extra extensions from the selected root partition.
212strlcpy(dirSpecExtra, "/Extra/", sizeof(dirSpecExtra));
213if (FileLoadDrivers(dirSpecExtra, 0) != 0)
214{
215// If failed, then try to load Extra extensions from the boot partition
216// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
217if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
218|| (gRAMDiskVolume && gRAMDiskBTAliased) )
219{
220// Next try a specfic OS version folder ie 10.5
221sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion[0]);
222if (FileLoadDrivers(dirSpecExtra, 0) != 0) {
223// Next we'll try the base
224strlcpy(dirSpecExtra, "bt(0,0)/Extra/", sizeof(dirSpecExtra));
225FileLoadDrivers(dirSpecExtra, 0);
226}
227}
228}
229if(!gHaveKernelCache)
230{
231// Don't load main driver (from /System/Library/Extentions) if gHaveKernelCache is set.
232// since these drivers will already be in the kernel cache.
233// NOTE: when gHaveKernelCache, xnu cannot (by default) load *any* extra kexts from the bootloader.
234// The /Extra code is not disabled in this case due to a kernel patch that allows for this to happen.
235
236// Also try to load Extensions from boot helper partitions.
237if (gBootVolume->flags & kBVFlagBooter)
238{
239strlcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/", sizeof(dirSpecExtra));
240if (FileLoadDrivers(dirSpecExtra, 0) != 0)
241{
242strlcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/", sizeof(dirSpecExtra));
243if (FileLoadDrivers(dirSpecExtra, 0) != 0)
244{
245strlcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/", sizeof(dirSpecExtra));
246FileLoadDrivers(dirSpecExtra, 0);
247}
248}
249}
250
251if (gMKextName[0] != '\0')
252{
253verbose("LoadDrivers: Loading from '%s'\n", gMKextName);
254if ( LoadDriverMKext(gMKextName) != 0 )
255{
256error("Could not load %s\n", gMKextName);
257return -1;
258}
259}
260else
261{
262verbose("Attempting to loading drivers from standard repositories:\n");
263
264if ( (gMacOSVersion[3] == '9') || ((gMacOSVersion[3] == '1') && ((gMacOSVersion[4] == '0') || (gMacOSVersion[4] == '1') || (gMacOSVersion[4] == '2') ) )) // issue 352
265{
266verbose("\t- Third party extensions search path: /Library/Extensions\n");
267strlcpy(gExtensionsSpec, dirSpec, 4087); /* 4096 - sizeof("Library/") mean 4096 - 9 = 4087 */
268strcat(gExtensionsSpec, "Library/");
269FileLoadDrivers(gExtensionsSpec, 0);
270}
271
272verbose("\t- Apple extensions search path: /System/Library/Extensions\n");
273strlcpy(gExtensionsSpec, dirSpec, 4080); /* 4096 - sizeof("System/Library/") mean 4096 -16 = 4080 */
274strcat(gExtensionsSpec, "System/Library/");
275FileLoadDrivers(gExtensionsSpec, 0);
276}
277
278}
279}
280else
281{
282return 0;
283}
284
285MatchPersonalities();
286
287MatchLibraries();
288
289LoadMatchedModules();
290
291return 0;
292}
293
294//==========================================================================
295// FileLoadMKext
296static long FileLoadMKext( const char *dirSpec, const char *extDirSpec )
297{
298longret, flags;
299u_int32_ttime, time2;
300charaltDirSpec[512];
301
302snprintf(altDirSpec, sizeof(altDirSpec), "%s%s", dirSpec, extDirSpec);
303ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
304
305if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
306{
307ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
308
309if ((ret != 0)
310|| ((flags & kFileTypeMask) != kFileTypeDirectory)
311|| (((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
312{
313snprintf(gDriverSpec, sizeof(altDirSpec) + 18, "%sExtensions.mkext", altDirSpec);
314verbose("LoadDrivers: Loading from '%s'\n", gDriverSpec);
315
316if (LoadDriverMKext(gDriverSpec) == 0)
317{
318return 0;
319}
320}
321}
322return -1;
323}
324
325//==========================================================================
326// FileLoadDrivers
327long FileLoadDrivers( char *dirSpec, long plugin )
328{
329long longindex;
330longret, length, flags, bundleType;
331longresult = -1;
332u_int32_ttime;
333const char* name;
334
335if ( !plugin )
336{
337// First try 10.6's path for loading Extensions.mkext.
338if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0) {
339return 0;
340}
341
342// Next try the legacy path.
343else if (FileLoadMKext(dirSpec, "") == 0)
344{
345return 0;
346}
347
348strcat(dirSpec, "Extensions");
349}
350
351index = 0;
352while (1)
353{
354ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
355if (ret == -1) {
356break;
357}
358
359// Make sure this is a directory.
360if ((flags & kFileTypeMask) != kFileTypeDirectory)
361{
362continue;
363}
364
365// Make sure this is a kext.
366length = strlen(name);
367if (strncmp(name + length - 5, ".kext", sizeof(".kext") ))
368{
369continue;
370}
371
372// Save the file name.
373strlcpy(gFileName, name, 4096);
374
375// Determine the bundle type.
376snprintf(gTempSpec, 4096, "%s/%s", dirSpec, gFileName);
377ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
378if (ret == 0)
379{
380bundleType = kCFBundleType2;
381}
382else
383{
384bundleType = kCFBundleType3;
385}
386
387if (!plugin)
388{
389snprintf(gDriverSpec, 4096, "%s/%s/%sPlugIns", dirSpec, gFileName, (bundleType == kCFBundleType2) ? "Contents/" : "");
390}
391
392ret = LoadDriverPList(dirSpec, gFileName, bundleType);
393
394if (result != 0)
395{
396result = ret;
397}
398
399if (!plugin)
400{
401FileLoadDrivers(gDriverSpec, 1);
402}
403}
404
405return result;
406}
407
408//==========================================================================
409//
410long NetLoadDrivers( char *dirSpec )
411{
412long tries;
413
414#if NODEF
415long cnt;
416
417// Get the name of the kernel
418cnt = strlen(gBootFile);
419while (cnt--) {
420if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ','))
421{
422cnt++;
423break;
424}
425}
426#endif
427
428// INTEL modification
429snprintf(gDriverSpec, 4096, "%s%s.mkext", dirSpec, bootInfo->bootFile);
430
431verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
432
433tries = 3;
434while (tries--)
435{
436if (LoadDriverMKext(gDriverSpec) == 0)
437{
438break;
439}
440}
441if (tries == -1)
442{
443return -1;
444}
445
446return 0;
447}
448
449//==========================================================================
450// loadDriverMKext
451long LoadDriverMKext( char *fileSpec )
452{
453unsigned longdriversAddr, driversLength;
454longlength;
455charsegName[32];
456DriversPackage*package;
457
458#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
459
460// Load the MKext.
461length = LoadThinFatFile(fileSpec, (void **)&package);
462if (length < sizeof (DriversPackage))
463{
464return -1;
465}
466
467// call hook to notify modules that the mkext has been loaded
468execute_hook("LoadDriverMKext", (void *)fileSpec, (void *)package, (void *) &length, NULL);
469
470
471// Verify the MKext.
472if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
473( GetPackageElement(signature2) != kDriverPackageSignature2) ||
474( GetPackageElement(length) > kLoadSize ) ||
475( GetPackageElement(adler32) !=
476Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
477{
478return -1;
479}
480
481// Make space for the MKext.
482driversLength = GetPackageElement(length);
483driversAddr = AllocateKernelMemory(driversLength);
484
485// Copy the MKext.
486memcpy((void *)driversAddr, (void *)package, driversLength);
487
488// Add the MKext to the memory map.
489snprintf(segName, sizeof(segName), "DriversPackage-%lx", driversAddr);
490AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT);
491
492return 0;
493}
494
495//==========================================================================
496// LoadDriverPList
497long LoadDriverPList( char *dirSpec, char *name, long bundleType )
498{
499long length, executablePathLength, bundlePathLength;
500ModulePtr module;
501TagPtr personalities;
502char * buffer = 0;
503char * tmpExecutablePath = 0;
504char * tmpBundlePath = 0;
505long ret = -1;
506
507do{
508// Save the driver path.
509
510if(name)
511{
512snprintf(gFileSpec, 4096, "%s/%s/%s", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
513}
514else
515{
516snprintf(gFileSpec, 4096, "%s/%s", dirSpec, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
517}
518executablePathLength = strlen(gFileSpec) + 1;
519
520tmpExecutablePath = malloc(executablePathLength);
521if (tmpExecutablePath == 0) {
522break;
523}
524strlcpy(tmpExecutablePath, gFileSpec, executablePathLength);
525
526if(name)
527{
528snprintf(gFileSpec, 4096, "%s/%s", dirSpec, name);
529}
530else
531{
532strncpy(gFileSpec, dirSpec, 4096);
533}
534bundlePathLength = strlen(gFileSpec) + 1;
535
536tmpBundlePath = malloc(bundlePathLength);
537if (tmpBundlePath == 0)
538{
539break;
540}
541
542strlcpy(tmpBundlePath, gFileSpec, bundlePathLength);
543
544// Construct the file spec to the plist, then load it.
545
546if(name)
547{
548snprintf(gFileSpec, 4096, "%s/%s/%sInfo.plist", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/" : "");
549}
550else
551{
552snprintf(gFileSpec, 4096, "%s/%sInfo.plist", dirSpec, (bundleType == kCFBundleType2) ? "Contents/" : "");
553}
554
555length = LoadFile(gFileSpec);
556
557if (length == -1)
558{
559break;
560}
561
562length = length + 1;
563buffer = malloc(length);
564
565if (buffer == 0)
566{
567break;
568}
569
570strlcpy(buffer, (char *)kLoadAddr, length);
571
572// Parse the plist.
573
574ret = ParseXML(buffer, &module, &personalities);
575
576if (ret != 0) {
577break;
578}
579
580if (!module) // cparm
581{
582ret = -1;
583break;
584} // Should never happen but it will make the compiler happy
585
586// Allocate memory for the driver path and the plist.
587
588module->executablePath = tmpExecutablePath;
589module->bundlePath = tmpBundlePath;
590module->bundlePathLength = bundlePathLength;
591module->plistAddr = malloc(length);
592
593if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
594{
595break;
596}
597
598// Save the driver path in the module.
599//strcpy(module->driverPath, tmpDriverPath);
600tmpExecutablePath = 0;
601tmpBundlePath = 0;
602
603// Add the plist to the module.
604
605strlcpy(module->plistAddr, (char *)kLoadAddr, length);
606module->plistLength = length;
607
608// Add the module to the end of the module list.
609
610if (gModuleHead == 0) {
611gModuleHead = module;
612} else {
613gModuleTail->nextModule = module;
614}
615gModuleTail = module;
616
617// Add the persionalities to the personality list.
618
619if (personalities) {
620personalities = personalities->tag;
621}
622while (personalities != 0)
623{
624if (gPersonalityHead == 0) {
625gPersonalityHead = personalities->tag;
626} else {
627gPersonalityTail->tagNext = personalities->tag;
628}
629
630gPersonalityTail = personalities->tag;
631personalities = personalities->tagNext;
632}
633
634ret = 0;
635}
636while (0);
637
638if ( buffer ) {
639free( buffer );
640}
641if ( tmpExecutablePath ) {
642free( tmpExecutablePath );
643}
644if ( tmpBundlePath ) {
645free( tmpBundlePath );
646}
647return ret;
648}
649
650//==========================================================================
651// LoadMatchedModules
652long LoadMatchedModules( void )
653{
654TagPtr prop;
655ModulePtr module;
656char *fileName, segName[32];
657DriverInfoPtr driver;
658long length, driverAddr, driverLength;
659void *executableAddr = 0;
660
661module = gModuleHead;
662
663while (module != 0)
664{
665if (module->willLoad)
666{
667prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
668
669if (prop != 0)
670{
671fileName = prop->string;
672snprintf(gFileSpec, 4096, "%s%s", module->executablePath, fileName);
673
674length = LoadThinFatFile(gFileSpec, &executableAddr);
675if (length == 0)
676{
677length = LoadFile(gFileSpec);
678executableAddr = (void *)kLoadAddr;
679}
680//printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getchar();
681}
682else
683{
684length = 0;
685}
686
687if ((length != -1) && executableAddr)
688{
689//driverModuleAddr = (void *)kLoadAddr;
690//if (length != 0)
691//{
692//ThinFatFile(&driverModuleAddr, &length);
693//}
694
695// Make make in the image area.
696
697execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
698
699driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
700driverAddr = AllocateKernelMemory(driverLength);
701
702// Set up the DriverInfo.
703driver = (DriverInfoPtr)driverAddr;
704driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
705driver->plistLength = module->plistLength;
706
707if (length != 0)
708{
709driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
710 module->plistLength);
711driver->executableLength = length;
712}
713else
714{
715driver->executableAddr = 0;
716driver->executableLength = 0;
717}
718
719driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
720 module->plistLength + driver->executableLength);
721driver->bundlePathLength = module->bundlePathLength;
722
723// Save the plist, module and bundle.
724strlcpy(driver->plistAddr, module->plistAddr, driver->plistLength);
725
726if (length != 0)
727{
728memcpy(driver->executableAddr, executableAddr, length);
729}
730
731strlcpy(driver->bundlePathAddr, module->bundlePath, module->bundlePathLength);
732
733// Add an entry to the memory map.
734snprintf(segName, sizeof(segName), "Driver-%lx", (unsigned long)driver);
735AllocateMemoryRange(segName, driverAddr, driverLength,
736kBootDriverTypeKEXT);
737}
738}
739module = module->nextModule;
740}
741
742return 0;
743}
744
745//==========================================================================
746// MatchPersonalities
747static long MatchPersonalities( void )
748{
749/* IONameMatch support not implemented */
750return 0;
751}
752
753//==========================================================================
754// MatchLibraries
755static long MatchLibraries( void )
756{
757TagPtr prop;
758TagPtr prop2;
759ModulePtr module;
760ModulePtr module2;
761long done;
762
763do {
764done = 1;
765module = gModuleHead;
766
767while (module != 0)
768{
769if (module->willLoad == 1)
770{
771prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
772
773if (prop != 0)
774{
775prop = prop->tag;
776
777while (prop != 0)
778{
779module2 = gModuleHead;
780
781while (module2 != 0)
782{
783prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
784
785if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
786{
787if (module2->willLoad == 0)
788{
789module2->willLoad = 1;
790}
791break;
792}
793module2 = module2->nextModule;
794}
795prop = prop->tagNext;
796}
797}
798module->willLoad = 2;
799done = 0;
800}
801module = module->nextModule;
802}
803}
804while (!done);
805
806return 0;
807}
808
809//==========================================================================
810// FindModule
811
812#if NOTDEF
813static ModulePtr FindModule( char *name )
814{
815ModulePtr module;
816TagPtr prop;
817
818module = gModuleHead;
819
820while (module != 0)
821{
822prop = GetProperty(module->dict, kPropCFBundleIdentifier);
823
824if ((prop != 0) && !strcmp(name, prop->string))
825{
826break;
827}
828
829module = module->nextModule;
830}
831
832return module;
833}
834#endif /* NOTDEF */
835
836//==========================================================================
837// ParseXML
838static long ParseXML( char *buffer, ModulePtr *module, TagPtr *personalities )
839{
840longlength;
841longpos = 0;
842TagPtrmoduleDict;
843TagPtrrequired;
844ModulePtrtmpModule;
845
846while (1)
847{
848length = XMLParseNextTag(buffer + pos, &moduleDict);
849if (length == -1)
850{
851break;
852}
853
854pos += length;
855
856if (moduleDict == 0)
857{
858continue;
859}
860if (moduleDict->type == kTagTypeDict)
861{
862break;
863}
864XMLFreeTag(moduleDict);
865}
866
867if (length == -1)
868{
869return -1;
870}
871
872required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
873
874if ( (required == 0) || (required->type != kTagTypeString) || !strncmp(required->string, "Safe Boot", sizeof("Safe Boot")))
875{
876XMLFreeTag(moduleDict);
877return -2;
878}
879
880tmpModule = malloc(sizeof(Module));
881if (tmpModule == 0)
882{
883XMLFreeTag(moduleDict);
884return -1;
885}
886tmpModule->dict = moduleDict;
887
888// For now, load any module that has OSBundleRequired != "Safe Boot".
889
890tmpModule->willLoad = 1;
891
892*module = tmpModule;
893
894// Get the personalities.
895
896*personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
897
898return 0;
899}
900
901#if NOTDEF
902static char gPlatformName[64];
903#endif
904
905long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
906{
907long ret = 0;
908compressed_kernel_header *kernel_header = (compressed_kernel_header *)binary;
909u_int32_t uncompressed_size = 0, size = 0, adler32 = 0;
910void *buffer = NULL;
911unsigned long len = 0;
912
913/*#if 0
914printf("kernel header:\n");
915printf("signature: 0x%x\n", kernel_header->signature);
916printf("compress_type: 0x%x\n", kernel_header->compress_type);
917printf("adler32: 0x%x\n", kernel_header->adler32);
918printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
919printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
920getchar();
921#endif*/
922
923if (kernel_header->signature == OSSwapBigToHostConstInt32('comp'))
924{
925DBG("Decompressing Kernel Cache:\n");
926
927if ((kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) &&
928(kernel_header->compress_type != OSSwapBigToHostConstInt32('lzvn')))
929{
930error("\tERROR: kernel compression is bad!\n");
931return -1;
932}
933
934if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
935{
936verbose ("\t- Decompressing Kernel Using lzss\n");
937}
938
939if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
940{
941verbose ("\t- Decompressing Kernel Using lzvn\n");
942}
943
944#if NOTDEF
945if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
946{
947return -1;
948}
949
950if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
951{
952return -1;
953}
954#endif
955uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
956binary = buffer = malloc(uncompressed_size);
957
958// MinusZwei
959size = 0;
960switch (kernel_header->compress_type)
961{
962case OSSwapBigToHostConstInt32('lzvn'):
963size = lzvn_decode(binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
964break;
965
966case OSSwapBigToHostConstInt32('lzss'):
967size = decompress_lzss((u_int8_t *)binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
968break;
969
970default:
971break;
972}
973// MinusZwei
974
975if (uncompressed_size != size)
976{
977if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
978{
979error("ERROR! Size mismatch from lzvn (found: %x, expected: %x).\n", size, uncompressed_size);
980}
981
982if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
983{
984error("ERROR! size mismatch from lzss (found: %x, expected: %x).\n", size, uncompressed_size);
985}
986
987return -1;
988}
989
990adler32 = Adler32(binary, uncompressed_size);
991if (OSSwapBigToHostInt32(kernel_header->adler32) != adler32)
992{
993error("ERROR! Adler mismatch (found: %X, expected: %X).\n", adler32, OSSwapBigToHostInt32(kernel_header->adler32));
994return -1;
995}
996
997DBG("\n");
998}
999
1000ret = ThinFatFile(&binary, &len);
1001if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
1002{
1003archCpuType=CPU_TYPE_I386;
1004ret = ThinFatFile(&binary, &len);
1005}
1006
1007// Bungo: scan binary for Darwin Kernel Version string
1008useDarwinVersion = true;
1009uint32_t offset = 0;
1010strncpy(gDarwinBuildVerStr, "Darwin Kernel Version", sizeof(gDarwinBuildVerStr));
1011
1012while ((offset < 0xFFFFFFFF - (uint32_t)binary - 256) && memcmp(binary + offset, gDarwinBuildVerStr, 21))
1013{
1014offset++;
1015}
1016if (offset < 0xFFFFFFFF - (uint32_t)binary - 256)
1017{
1018strncpy(gDarwinBuildVerStr, (char *)(binary + offset), sizeof(gDarwinBuildVerStr));
1019}
1020else
1021{
1022strcat(gDarwinBuildVerStr, ": Unknown");
1023useDarwinVersion = false;
1024}
1025// Micky1979 use Bungo gDarwinBuildVerStr and split into gDarwinMajor, gDarwinMinor and gDarwinRev
1026if (useDarwinVersion)
1027{
1028useDarwinVersion = false;
1029const char *pattern = strstr(gDarwinBuildVerStr, "Darwin Kernel Version ")+22;
1030const char *until = strstr(pattern, ":");
1031size_t vlen = until - pattern;
1032char *ver = (char *)malloc(sizeof(char)*(len+1));
1033strncpy(ver, pattern, vlen);
1034ver[vlen] = '\0';
1035char *delim;
1036char *temp;
1037gDarwinMajor = -1; gDarwinMinor = -1; gDarwinRev = -1;
1038if (ver != NULL)
1039{
1040temp = ver;
1041int count = 1;
1042while ((delim = strsep_c(&ver, ".")) != NULL)
1043{
1044switch (count)
1045{
1046case 1: gDarwinMajor = atoi(delim); break;
1047case 2: gDarwinMinor = atoi(delim); break;
1048case 3: gDarwinRev = atoi(delim); break;
1049default: break;
1050}
1051count ++;
1052}
1053free(temp);
1054}
1055
1056if (gDarwinMajor >= 0 && gDarwinMinor >= 0 && gDarwinRev >= 0)
1057{
1058useDarwinVersion = true;
1059}
1060
1061switch (gDarwinMajor)
1062{
1063case 10:
1064switch (gDarwinMinor)
1065{
1066case 0: kernelOSVer = 0xA060000; break;
1067case 1: kernelOSVer = 0xA060100; break;
1068case 2: kernelOSVer = 0xA060200; break;
1069case 3: kernelOSVer = 0xA060300; break;
1070case 4: kernelOSVer = 0xA060400; break;
1071case 5: kernelOSVer = 0xA060500; break;
1072case 6: kernelOSVer = 0xA060600; break;
1073case 7: kernelOSVer = 0xA060700; break;
1074case 8: kernelOSVer = 0xA060800; break;
1075default:kernelOSVer = 0xA060800; break; //Last known kernel
1076}
1077break;
1078case 11:
1079switch (gDarwinMinor)
1080{
1081case 0: kernelOSVer = 0xA070000; break;
1082case 1: kernelOSVer = 0xA070100; break;
1083case 2: kernelOSVer = 0xA070200; break;
1084case 3: kernelOSVer = 0xA070300; break;
1085case 4:
1086switch (gDarwinRev)
1087{
1088case 0: kernelOSVer = 0xA070400; break;
1089case 1: kernelOSVer = 0xA070400; break;
1090case 2: kernelOSVer = 0xA070500; break;
1091default:kernelOSVer = 0xA070500; break; //Last known kernel
1092}
1093default:kernelOSVer = 0xA070500; break; //Last known kernel
1094}
1095break;
1096case 12:
1097switch (gDarwinMinor)
1098{
1099case 0: kernelOSVer = 0xA080000; break;
1100case 1: kernelOSVer = 0xA080100; break;
1101case 2: kernelOSVer = 0xA080200; break;
1102case 3: kernelOSVer = 0xA080300; break;
1103case 4: kernelOSVer = 0xA080400; break;
1104case 5: kernelOSVer = 0xA080500; break; // 10.8.5
1105case 6: kernelOSVer = 0xA080500; break; // 10.8.5 update
1106default:kernelOSVer = 0xA080500; break; //Last known kernel
1107}
1108break;
1109case 13:
1110switch (gDarwinMinor)
1111{
1112case 0: kernelOSVer = 0xA090000;
1113switch (gDarwinRev)
1114{
1115case 0: kernelOSVer = 0xA090000; break;
1116case 1: kernelOSVer = 0xA090000; break; // never exist (or released)
1117case 2: kernelOSVer = 0xA090100; break;
1118default:kernelOSVer = 0xA090100; break; //Last known kernel
1119}
1120break;
1121case 1: kernelOSVer = 0xA090100; break; // never exist (or released)
1122case 2: kernelOSVer = 0xA090200; break;
1123case 3: kernelOSVer = 0xA090300; break;
1124case 4: kernelOSVer = 0xA090400; break;
1125case 5: kernelOSVer = 0xA090500; break;
1126default:kernelOSVer = 0xA090500; break; //Last known kernel
1127}
1128break;
1129case 14:
1130switch (gDarwinMinor)
1131{
1132case 0: kernelOSVer = 0xA0A0000; break; // same kernel of 10.10.1
1133case 1: kernelOSVer = 0xA0A0100; break; // same kernel of 10.10
1134case 2: kernelOSVer = 0xA0A0200; break;
1135case 3: kernelOSVer = 0xA0A0300; break;
1136case 4: kernelOSVer = 0xA0A0400; break;
1137case 5: kernelOSVer = 0xA0A0500; break;
1138default:kernelOSVer = 0xA0A0500; break; //Last known kernel
1139}
1140break;
1141case 15:
1142switch (gDarwinMinor)
1143{
1144case 0: kernelOSVer = 0xA0B0000; break;
1145case 1: kernelOSVer = 0xA0B0100; break;
1146case 2: kernelOSVer = 0xA0B0200; break;
1147case 3: kernelOSVer = 0xA0B0300; break;
1148case 4: kernelOSVer = 0xA0B0400; break;
1149case 5: kernelOSVer = 0xA0B0500; break;
1150case 6: kernelOSVer = 0xA0B0600; break;
1151default:kernelOSVer = 0xA0B0600; break; //Last known kernel (add here updates)
1152}
1153break;
1154case 16:
1155switch (gDarwinMinor)
1156{
1157case 0: kernelOSVer = 0xA0C0000; break;
1158default:kernelOSVer = 0xA0C0000; break; //Last known kernel (add here updates)
1159}
1160break;
1161default:
1162kernelOSVer = 0xA0B0100;
1163break; //Last known kernel
1164}
1165}
1166else
1167{
1168switch (MacOSVerCurrent)
1169{
1170// Snow
1171case 0xA060000: gDarwinMajor = 10; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.6
1172case 0xA060100: gDarwinMajor = 10; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.6.1
1173case 0xA060200: gDarwinMajor = 10; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.6.2
1174case 0xA060300: gDarwinMajor = 10; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.6.3
1175case 0xA060400: gDarwinMajor = 10; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.6.4
1176case 0xA060500: gDarwinMajor = 10; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.6.5
1177case 0xA060600: gDarwinMajor = 10; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.6.6
1178case 0xA060700: gDarwinMajor = 10; gDarwinMinor = 7; gDarwinRev = 0; break; // 10.6.7
1179case 0xA060800: gDarwinMajor = 10; gDarwinMinor = 8; gDarwinRev = 0; break; // 10.6.8
1180// Lion
1181case 0xA070000: gDarwinMajor = 11; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.7
1182case 0xA070100: gDarwinMajor = 11; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.7.1
1183case 0xA070200: gDarwinMajor = 11; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.7.2
1184case 0xA070300: gDarwinMajor = 11; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.7.3
1185case 0xA070400: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.7.4
1186case 0xA070500: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 2; break; // 10.7.5
1187// ML
1188case 0xA080000: gDarwinMajor = 12; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.8
1189case 0xA080100: gDarwinMajor = 12; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.8.1
1190case 0xA080200: gDarwinMajor = 12; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.8.2
1191case 0xA080300: gDarwinMajor = 12; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.8.3
1192case 0xA080400: gDarwinMajor = 12; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.8.4
1193case 0xA080500: gDarwinMajor = 12; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.8.5
1194// Mavericks
1195case 0xA090000: gDarwinMajor = 13; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.9
1196case 0xA090100: gDarwinMajor = 13; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.9.1
1197case 0xA090200: gDarwinMajor = 13; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.9.2
1198case 0xA090300: gDarwinMajor = 13; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.9.3
1199case 0xA090400: gDarwinMajor = 13; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.9.4
1200case 0xA090500: gDarwinMajor = 13; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.9.5
1201// Yosemite
1202case 0xA0A0000: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10
1203case 0xA0A0100: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10.1
1204case 0xA0A0200: gDarwinMajor = 14; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.10.2
1205case 0xA0A0300: gDarwinMajor = 14; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.10.3
1206case 0xA0A0400: gDarwinMajor = 14; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.10.4
1207case 0xA0A0500: gDarwinMajor = 14; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.10.5
1208// El Capitan
1209case 0xA0B0000: gDarwinMajor = 15; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.11
1210case 0xA0B0100: gDarwinMajor = 15; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.11.1
1211case 0xA0B0200: gDarwinMajor = 15; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.11.2
1212case 0xA0B0300: gDarwinMajor = 15; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.11.3
1213case 0xA0B0400: gDarwinMajor = 15; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.11.4
1214case 0xA0B0500: gDarwinMajor = 15; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.11.5
1215case 0xA0B0600: gDarwinMajor = 15; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.11.6
1216// Sierra
1217case 0xA0C0000: gDarwinMajor = 16; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.12
1218// default = last known kernel
1219default: gDarwinMajor = 16; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.12;
1220}
1221}
1222
1223// Notify modules that the kernel has been decompressed, thinned and is about to be decoded
1224execute_hook("DecodeKernel", (void *)binary, NULL, NULL, NULL);
1225
1226/* ================================================================ */
1227
1228// Entry point
1229
1230/* ================================================================ */
1231
1232ret = DecodeMachO(binary, rentry, raddr, rsize);
1233if (ret < 0 && archCpuType == CPU_TYPE_X86_64)
1234{
1235archCpuType = CPU_TYPE_I386;
1236ret = DecodeMachO(binary, rentry, raddr, rsize);
1237}
1238
1239return ret;
1240}
1241

Archive Download this file

Revision: 2837