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
49struct Module {
50struct Module *nextModule;
51long willLoad;
52TagPtr dict;
53char *plistAddr;
54long plistLength;
55char *executablePath;
56char *bundlePath;
57long bundlePathLength;
58};
59typedef struct Module Module, *ModulePtr;
60
61struct DriverInfo {
62char *plistAddr;
63long plistLength;
64void *executableAddr;
65long executableLength;
66void *bundlePathAddr;
67long bundlePathLength;
68};
69typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
70
71#define kDriverPackageSignature1 'MKXT'
72#define kDriverPackageSignature2 'MOSX'
73
74struct DriversPackage {
75unsigned long signature1;
76unsigned long signature2;
77unsigned long length;
78unsigned long adler32;
79unsigned long version;
80unsigned long numDrivers;
81unsigned long reserved1;
82unsigned long reserved2;
83};
84typedef struct DriversPackage DriversPackage;
85
86enum {
87kCFBundleType2,
88kCFBundleType3
89};
90
91long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
92
93static inline unsigned long Adler32( unsigned char * buffer, long length );
94
95long FileLoadDrivers(char *dirSpec, long plugin);
96long NetLoadDrivers(char *dirSpec);
97long LoadDriverMKext(char *fileSpec);
98long LoadDriverPList(char *dirSpec, char *name, long bundleType);
99long LoadMatchedModules(void);
100
101static long MatchPersonalities(void);
102static long MatchLibraries(void);
103
104#ifdef NOTDEF
105static ModulePtr FindModule(char *name);
106static void ThinFatFile(void **loadAddrP, unsigned long *lengthP);
107#endif
108static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities);
109static long InitDriverSupport(void);
110
111ModulePtr gModuleHead, gModuleTail;
112static TagPtrgPersonalityHead, gPersonalityTail;
113static char*gExtensionsSpec;
114static char*gDriverSpec;
115static char*gFileSpec;
116static char*gTempSpec;
117static char*gFileName;
118// Bungo:
119char gDarwinBuildVerStr[256] = "Darwin Kernel Version";
120
121static inline unsigned long Adler32( unsigned char *buffer, long length )
122{
123long cnt;
124unsigned long result, lowHalf, highHalf;
125
126lowHalf = 1;
127highHalf = 0;
128
129for (cnt = 0; cnt < length; cnt++)
130{
131if ((cnt % 5000) == 0)
132{
133lowHalf %= 65521L;
134highHalf %= 65521L;
135}
136
137lowHalf += buffer[cnt];
138highHalf += lowHalf;
139}
140
141lowHalf %= 65521L;
142highHalf %= 65521L;
143
144result = (highHalf << 16) | lowHalf;
145
146return result;
147}
148
149//==========================================================================
150// InitDriverSupport
151static long InitDriverSupport( void )
152{
153gExtensionsSpec = malloc( 4096 );
154gDriverSpec = malloc( 4096 );
155gFileSpec = malloc( 4096 );
156gTempSpec = malloc( 4096 );
157gFileName = malloc( 4096 );
158
159if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
160{
161stop("InitDriverSupport error");
162}
163
164return 0;
165}
166
167//==========================================================================
168// LoadDrivers
169long LoadDrivers( char *dirSpec )
170{
171char dirSpecExtra[1024];
172
173if ( InitDriverSupport() != 0 )
174{
175return 0;
176}
177
178// ========================================
179
180// Load extra drivers if a hook has been installed.
181if (LoadExtraDrivers_p != NULL)
182{
183(*LoadExtraDrivers_p)(&FileLoadDrivers);
184}
185
186if ( gBootFileType == kNetworkDeviceType )
187{
188if (NetLoadDrivers(dirSpec) != 0)
189{
190error("LoadDrivers: Could not load drivers from the network\n");
191return -1;
192}
193}
194else if ( gBootFileType == kBlockDeviceType )
195{
196// First try to load Extra extensions from the ramdisk if isn't aliased as bt(0,0).
197if (gRAMDiskVolume && !gRAMDiskBTAliased)
198{
199strcpy(dirSpecExtra, "rd(0,0)/Extra/");
200FileLoadDrivers(dirSpecExtra, 0);
201}
202verbose("Attempting to loading drivers from \"Extra\" repository:\n");
203
204// =====================================================================
205// Firstly try to load drivers from Common folder
206sprintf(dirSpecExtra, "bt(0,0)/Extra/Common/");
207FileLoadDrivers(dirSpecExtra, 0);
208// =====================================================================
209
210// Next try to load Extra extensions from the selected root partition.
211strlcpy(dirSpecExtra, "/Extra/", sizeof(dirSpecExtra));
212if (FileLoadDrivers(dirSpecExtra, 0) != 0)
213{
214// If failed, then try to load Extra extensions from the boot partition
215// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
216if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
217|| (gRAMDiskVolume && gRAMDiskBTAliased) )
218{
219// Next try a specfic OS version folder ie 10.5
220sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion[0]);
221if (FileLoadDrivers(dirSpecExtra, 0) != 0)
222{
223// Next we'll try the base
224strlcpy(dirSpecExtra, "bt(0,0)/Extra/", sizeof(dirSpecExtra));
225FileLoadDrivers(dirSpecExtra, 0);
226}
227}
228}
229
230if(!gHaveKernelCache)
231{
232// Don't load main driver (from /System/Library/Extentions) if gHaveKernelCache is set.
233// since these drivers will already be in the kernel cache.
234// NOTE: when gHaveKernelCache, xnu cannot (by default) load *any* extra kexts from the bootloader.
235// The /Extra code is not disabled in this case due to a kernel patch that allows for this to happen.
236
237// Also try to load Extensions from boot helper partitions.
238if (gBootVolume->flags & kBVFlagBooter)
239{
240strlcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/", sizeof(dirSpecExtra));
241if (FileLoadDrivers(dirSpecExtra, 0) != 0)
242{
243strlcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/", sizeof(dirSpecExtra));
244if (FileLoadDrivers(dirSpecExtra, 0) != 0)
245{
246strlcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/", sizeof(dirSpecExtra));
247FileLoadDrivers(dirSpecExtra, 0);
248}
249}
250}
251
252if (gMKextName[0] != '\0')
253{
254verbose("LoadDrivers: Loading from '%s'\n", gMKextName);
255if ( LoadDriverMKext(gMKextName) != 0 )
256{
257error("Could not load %s\n", gMKextName);
258return -1;
259}
260}
261else
262{
263verbose("Attempting to load drivers from standard repositories:\n");
264
265if ( (gMacOSVersion[3] == '9') || ((gMacOSVersion[3] == '1') && ((gMacOSVersion[4] == '0') || (gMacOSVersion[4] == '1') || (gMacOSVersion[4] == '2') ) )) // issue 352
266{
267verbose("\t- Third party extensions search path: /Library/Extensions\n");
268strlcpy(gExtensionsSpec, dirSpec, 4087); /* 4096 - sizeof("Library/") mean 4096 - 9 = 4087 */
269strcat(gExtensionsSpec, "Library/");
270FileLoadDrivers(gExtensionsSpec, 0);
271}
272
273verbose("\t- Apple extensions search path: /System/Library/Extensions\n");
274strlcpy(gExtensionsSpec, dirSpec, 4080); /* 4096 - sizeof("System/Library/") mean 4096 -16 = 4080 */
275strcat(gExtensionsSpec, "System/Library/");
276FileLoadDrivers(gExtensionsSpec, 0);
277}
278
279}
280}
281else
282{
283return 0;
284}
285
286MatchPersonalities();
287
288MatchLibraries();
289
290LoadMatchedModules();
291
292return 0;
293}
294
295//==========================================================================
296// FileLoadMKext
297static long FileLoadMKext( const char *dirSpec, const char *extDirSpec )
298{
299longret, flags;
300u_int32_ttime, time2;
301charaltDirSpec[512];
302
303snprintf(altDirSpec, sizeof(altDirSpec), "%s%s", dirSpec, extDirSpec);
304ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
305
306if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
307{
308ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
309
310if ((ret != 0)
311|| ((flags & kFileTypeMask) != kFileTypeDirectory)
312|| (((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
313{
314snprintf(gDriverSpec, sizeof(altDirSpec) + 18, "%sExtensions.mkext", altDirSpec);
315verbose("LoadDrivers: Loading from '%s'\n", gDriverSpec);
316
317if (LoadDriverMKext(gDriverSpec) == 0)
318{
319return 0;
320}
321}
322}
323return -1;
324}
325
326//==========================================================================
327// FileLoadDrivers
328long FileLoadDrivers( char *dirSpec, long plugin )
329{
330long longindex;
331longret, length, flags, bundleType;
332longresult = -1;
333u_int32_ttime;
334const char* name;
335
336if ( !plugin )
337{
338// First try 10.6's path for loading Extensions.mkext.
339if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0) {
340return 0;
341}
342
343// Next try the legacy path.
344else if (FileLoadMKext(dirSpec, "") == 0)
345{
346return 0;
347}
348
349strcat(dirSpec, "Extensions");
350}
351
352index = 0;
353while (1)
354{
355ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
356if (ret == -1) {
357break;
358}
359
360// Make sure this is a directory.
361if ((flags & kFileTypeMask) != kFileTypeDirectory)
362{
363continue;
364}
365
366// Make sure this is a kext.
367length = strlen(name);
368if (strncmp(name + length - 5, ".kext", sizeof(".kext") ))
369{
370continue;
371}
372
373// Save the file name.
374strlcpy(gFileName, name, 4096);
375
376// Determine the bundle type.
377snprintf(gTempSpec, 4096, "%s/%s", dirSpec, gFileName);
378ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
379if (ret == 0)
380{
381bundleType = kCFBundleType2;
382}
383else
384{
385bundleType = kCFBundleType3;
386}
387
388if (!plugin)
389{
390snprintf(gDriverSpec, 4096, "%s/%s/%sPlugIns", dirSpec, gFileName, (bundleType == kCFBundleType2) ? "Contents/" : "");
391}
392
393ret = LoadDriverPList(dirSpec, gFileName, bundleType);
394
395if (result != 0)
396{
397result = ret;
398}
399
400if (!plugin)
401{
402FileLoadDrivers(gDriverSpec, 1);
403}
404}
405
406return result;
407}
408
409//==========================================================================
410//
411long NetLoadDrivers( char *dirSpec )
412{
413long tries;
414
415#if NODEF
416long cnt;
417
418// Get the name of the kernel
419cnt = strlen(gBootFile);
420while (cnt--) {
421if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ','))
422{
423cnt++;
424break;
425}
426}
427#endif
428
429// INTEL modification
430snprintf(gDriverSpec, 4096, "%s%s.mkext", dirSpec, bootInfo->bootFile);
431
432verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
433
434tries = 3;
435while (tries--)
436{
437if (LoadDriverMKext(gDriverSpec) == 0)
438{
439break;
440}
441}
442if (tries == -1)
443{
444return -1;
445}
446
447return 0;
448}
449
450//==========================================================================
451// loadDriverMKext
452long LoadDriverMKext( char *fileSpec )
453{
454unsigned longdriversAddr, driversLength;
455longlength;
456charsegName[32];
457DriversPackage*package;
458
459#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
460
461// Load the MKext.
462length = LoadThinFatFile(fileSpec, (void **)&package);
463if (length < sizeof (DriversPackage))
464{
465return -1;
466}
467
468// call hook to notify modules that the mkext has been loaded
469execute_hook("LoadDriverMKext", (void *)fileSpec, (void *)package, (void *) &length, NULL);
470
471
472// Verify the MKext.
473if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
474( GetPackageElement(signature2) != kDriverPackageSignature2) ||
475( GetPackageElement(length) > kLoadSize ) ||
476( GetPackageElement(adler32) !=
477Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
478{
479return -1;
480}
481
482// Make space for the MKext.
483driversLength = GetPackageElement(length);
484driversAddr = AllocateKernelMemory(driversLength);
485
486// Copy the MKext.
487memcpy((void *)driversAddr, (void *)package, driversLength);
488
489// Add the MKext to the memory map.
490snprintf(segName, sizeof(segName), "DriversPackage-%lx", driversAddr);
491AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT);
492
493return 0;
494}
495
496//==========================================================================
497// LoadDriverPList
498long LoadDriverPList( char *dirSpec, char *name, long bundleType )
499{
500longlength, executablePathLength, bundlePathLength;
501ModulePtrmodule;
502TagPtrpersonalities;
503char*buffer = 0;
504char*tmpExecutablePath = 0;
505char*tmpBundlePath = 0;
506longret = -1;
507
508do {
509// Save the driver path.
510
511if(name)
512{
513snprintf(gFileSpec, 4096, "%s/%s/%s", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
514}
515else
516{
517snprintf(gFileSpec, 4096, "%s/%s", dirSpec, (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
518}
519executablePathLength = strlen(gFileSpec) + 1;
520
521tmpExecutablePath = malloc(executablePathLength);
522if (tmpExecutablePath == 0) {
523break;
524}
525strlcpy(tmpExecutablePath, gFileSpec, executablePathLength);
526
527if(name)
528{
529snprintf(gFileSpec, 4096, "%s/%s", dirSpec, name);
530}
531else
532{
533strncpy(gFileSpec, dirSpec, 4096);
534}
535bundlePathLength = strlen(gFileSpec) + 1;
536
537tmpBundlePath = malloc(bundlePathLength);
538if (tmpBundlePath == 0)
539{
540break;
541}
542
543strlcpy(tmpBundlePath, gFileSpec, bundlePathLength);
544
545// Construct the file spec to the plist, then load it.
546
547if(name)
548{
549snprintf(gFileSpec, 4096, "%s/%s/%sInfo.plist", dirSpec, name, (bundleType == kCFBundleType2) ? "Contents/" : "");
550}
551else
552{
553snprintf(gFileSpec, 4096, "%s/%sInfo.plist", dirSpec, (bundleType == kCFBundleType2) ? "Contents/" : "");
554}
555
556length = LoadFile(gFileSpec);
557
558if (length == -1)
559{
560break;
561}
562
563length = length + 1;
564buffer = malloc(length);
565
566if (buffer == 0)
567{
568break;
569}
570
571strlcpy(buffer, (char *)kLoadAddr, length);
572
573// Parse the plist.
574
575ret = ParseXML(buffer, &module, &personalities);
576
577if (ret != 0) {
578break;
579}
580
581if (!module) // cparm
582{
583ret = -1;
584break;
585} // Should never happen but it will make the compiler happy
586
587// Allocate memory for the driver path and the plist.
588
589module->executablePath = tmpExecutablePath;
590module->bundlePath = tmpBundlePath;
591module->bundlePathLength = bundlePathLength;
592module->plistAddr = malloc(length);
593
594if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
595{
596break;
597}
598
599// Save the driver path in the module.
600//strcpy(module->driverPath, tmpDriverPath);
601tmpExecutablePath = 0;
602tmpBundlePath = 0;
603
604// Add the plist to the module.
605
606strlcpy(module->plistAddr, (char *)kLoadAddr, length);
607module->plistLength = length;
608
609// Add the module to the end of the module list.
610
611if (gModuleHead == 0) {
612gModuleHead = module;
613} else {
614gModuleTail->nextModule = module;
615}
616gModuleTail = module;
617
618// Add the persionalities to the personality list.
619
620if (personalities) {
621personalities = personalities->tag;
622}
623while (personalities != 0)
624{
625if (gPersonalityHead == 0) {
626gPersonalityHead = personalities->tag;
627} else {
628gPersonalityTail->tagNext = personalities->tag;
629}
630
631gPersonalityTail = personalities->tag;
632personalities = personalities->tagNext;
633}
634
635ret = 0;
636}
637while (0);
638
639if ( buffer ) {
640free( buffer );
641}
642if ( tmpExecutablePath ) {
643free( tmpExecutablePath );
644}
645if ( tmpBundlePath ) {
646free( tmpBundlePath );
647}
648return ret;
649}
650
651//==========================================================================
652// LoadMatchedModules
653long LoadMatchedModules( void )
654{
655TagPtrprop;
656ModulePtrmodule;
657char*fileName, segName[32];
658DriverInfoPtrdriver;
659longlength, driverAddr, driverLength;
660void*executableAddr = 0;
661
662module = gModuleHead;
663
664while (module != 0)
665{
666if (module->willLoad)
667{
668prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
669
670if (prop != 0)
671{
672fileName = prop->string;
673snprintf(gFileSpec, 4096, "%s%s", module->executablePath, fileName);
674
675length = LoadThinFatFile(gFileSpec, &executableAddr);
676if (length == 0)
677{
678length = LoadFile(gFileSpec);
679executableAddr = (void *)kLoadAddr;
680}
681//printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getchar();
682}
683else
684{
685length = 0;
686}
687
688if ((length != -1) && executableAddr)
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;
839TagPtridentifier;
840ModulePtrtmpModule;
841
842while (1)
843{
844length = XMLParseNextTag(buffer + pos, &moduleDict);
845if (length == -1)
846{
847break;
848}
849
850pos += length;
851
852if (moduleDict == 0)
853{
854continue;
855}
856if (moduleDict->type == kTagTypeDict)
857{
858break;
859}
860XMLFreeTag(moduleDict);
861}
862
863if (length == -1)
864{
865return -1;
866}
867
868required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
869
870if ( (required == 0) || (required->type != kTagTypeString) || !strncmp(required->string, "Safe Boot", sizeof("Safe Boot")))
871{
872identifier = XMLGetProperty(moduleDict, "CFBundleIdentifier");
873
874if (strcmp(identifier->string, "com.apple.driver.AppleSMC") == 0)
875{
876//verbose("\tForced load of: AppleSMC.kext");
877}
878else
879{
880XMLFreeTag(moduleDict);
881return -2;
882}
883}
884
885tmpModule = malloc(sizeof(Module));
886if (tmpModule == 0)
887{
888XMLFreeTag(moduleDict);
889return -1;
890}
891tmpModule->dict = moduleDict;
892
893// For now, load any module that has OSBundleRequired != "Safe Boot".
894
895tmpModule->willLoad = 1;
896
897*module = tmpModule;
898
899// Get the personalities.
900
901*personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
902
903return 0;
904}
905
906#if NOTDEF
907static char gPlatformName[64];
908#endif
909
910long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
911{
912long ret = 0;
913compressed_kernel_header *kernel_header = (compressed_kernel_header *)binary;
914u_int32_t uncompressed_size = 0, size = 0, adler32 = 0;
915void *buffer = NULL;
916unsigned long len = 0;
917
918/*#if 0
919printf("kernel header:\n");
920printf("signature: 0x%x\n", kernel_header->signature);
921printf("compress_type: 0x%x\n", kernel_header->compress_type);
922printf("adler32: 0x%x\n", kernel_header->adler32);
923printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
924printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
925getchar();
926#endif*/
927
928if (kernel_header->signature == OSSwapBigToHostConstInt32('comp'))
929{
930DBG("Decompressing Kernel Cache:\n");
931
932if ((kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) &&
933(kernel_header->compress_type != OSSwapBigToHostConstInt32('lzvn')))
934{
935error("\tERROR: kernel compression is bad!\n");
936return -1;
937}
938
939if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
940{
941verbose ("\t- Decompressing Kernel Using lzss\n");
942}
943
944if (kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
945{
946verbose ("\t- Decompressing Kernel Using lzvn\n");
947}
948
949#if NOTDEF
950if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
951{
952return -1;
953}
954
955if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
956{
957return -1;
958}
959#endif
960uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
961binary = buffer = malloc(uncompressed_size);
962
963// MinusZwei
964size = 0;
965switch (kernel_header->compress_type)
966{
967case OSSwapBigToHostConstInt32('lzvn'):
968size = lzvn_decode(binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
969break;
970
971case OSSwapBigToHostConstInt32('lzss'):
972size = decompress_lzss((u_int8_t *)binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size));
973break;
974
975default:
976break;
977}
978// MinusZwei
979
980if (uncompressed_size != size)
981{
982if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn'))
983{
984error("ERROR! Size mismatch from lzvn (found: %x, expected: %x).\n", size, uncompressed_size);
985}
986
987if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss'))
988{
989error("ERROR! size mismatch from lzss (found: %x, expected: %x).\n", size, uncompressed_size);
990}
991
992return -1;
993}
994
995adler32 = Adler32(binary, uncompressed_size);
996if (OSSwapBigToHostInt32(kernel_header->adler32) != adler32)
997{
998error("ERROR! Adler mismatch (found: %X, expected: %X).\n", adler32, OSSwapBigToHostInt32(kernel_header->adler32));
999return -1;
1000}
1001
1002DBG("\n");
1003}
1004
1005ret = ThinFatFile(&binary, &len);
1006if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
1007{
1008archCpuType=CPU_TYPE_I386;
1009ret = ThinFatFile(&binary, &len);
1010}
1011
1012// Bungo: scan binary for Darwin Kernel Version string
1013useDarwinVersion = true;
1014uint32_t offset = 0;
1015strncpy(gDarwinBuildVerStr, "Darwin Kernel Version", sizeof(gDarwinBuildVerStr));
1016
1017while ((offset < 0xFFFFFFFF - (uint32_t)binary - 256) && memcmp(binary + offset, gDarwinBuildVerStr, 21))
1018{
1019offset++;
1020}
1021if (offset < 0xFFFFFFFF - (uint32_t)binary - 256)
1022{
1023strncpy(gDarwinBuildVerStr, (char *)(binary + offset), sizeof(gDarwinBuildVerStr));
1024}
1025else
1026{
1027strcat(gDarwinBuildVerStr, ": Unknown");
1028useDarwinVersion = false;
1029}
1030// Micky1979 use Bungo gDarwinBuildVerStr and split into gDarwinMajor, gDarwinMinor and gDarwinRev
1031if (useDarwinVersion)
1032{
1033useDarwinVersion = false;
1034const char *pattern = strstr(gDarwinBuildVerStr, "Darwin Kernel Version ")+22;
1035const char *until = strstr(pattern, ":");
1036size_t vlen = until - pattern;
1037char *ver = (char *)malloc(sizeof(char)*(len+1));
1038strncpy(ver, pattern, vlen);
1039ver[vlen] = '\0';
1040char *delim;
1041char *temp;
1042gDarwinMajor = -1; gDarwinMinor = -1; gDarwinRev = -1;
1043if (ver != NULL)
1044{
1045temp = ver;
1046int count = 1;
1047while ((delim = strsep_c(&ver, ".")) != NULL)
1048{
1049switch (count)
1050{
1051case 1: gDarwinMajor = atoi(delim); break;
1052case 2: gDarwinMinor = atoi(delim); break;
1053case 3: gDarwinRev = atoi(delim); break;
1054default: break;
1055}
1056count ++;
1057}
1058free(temp);
1059}
1060
1061if (gDarwinMajor >= 0 && gDarwinMinor >= 0 && gDarwinRev >= 0)
1062{
1063useDarwinVersion = true;
1064}
1065
1066switch (gDarwinMajor)
1067{
1068case 10:
1069switch (gDarwinMinor)
1070{
1071case 0: kernelOSVer = 0xA060000; break;
1072case 1: kernelOSVer = 0xA060100; break;
1073case 2: kernelOSVer = 0xA060200; break;
1074case 3: kernelOSVer = 0xA060300; break;
1075case 4: kernelOSVer = 0xA060400; break;
1076case 5: kernelOSVer = 0xA060500; break;
1077case 6: kernelOSVer = 0xA060600; break;
1078case 7: kernelOSVer = 0xA060700; break;
1079case 8: kernelOSVer = 0xA060800; break;
1080default:kernelOSVer = 0xA060800; break; //Last known kernel
1081}
1082break;
1083case 11:
1084switch (gDarwinMinor)
1085{
1086case 0: kernelOSVer = 0xA070000; break;
1087case 1: kernelOSVer = 0xA070100; break;
1088case 2: kernelOSVer = 0xA070200; break;
1089case 3: kernelOSVer = 0xA070300; break;
1090case 4:
1091switch (gDarwinRev)
1092{
1093case 0: kernelOSVer = 0xA070400; break;
1094case 1: kernelOSVer = 0xA070400; break;
1095case 2: kernelOSVer = 0xA070500; break;
1096default:kernelOSVer = 0xA070500; break; //Last known kernel
1097}
1098default:kernelOSVer = 0xA070500; break; //Last known kernel
1099}
1100break;
1101case 12:
1102switch (gDarwinMinor)
1103{
1104case 0: kernelOSVer = 0xA080000; break;
1105case 1: kernelOSVer = 0xA080100; break;
1106case 2: kernelOSVer = 0xA080200; break;
1107case 3: kernelOSVer = 0xA080300; break;
1108case 4: kernelOSVer = 0xA080400; break;
1109case 5: kernelOSVer = 0xA080500; break; // 10.8.5
1110case 6: kernelOSVer = 0xA080500; break; // 10.8.5 update
1111default:kernelOSVer = 0xA080500; break; //Last known kernel
1112}
1113break;
1114case 13:
1115switch (gDarwinMinor)
1116{
1117case 0: kernelOSVer = 0xA090000;
1118switch (gDarwinRev)
1119{
1120case 0: kernelOSVer = 0xA090000; break;
1121case 1: kernelOSVer = 0xA090000; break; // never exist (or released)
1122case 2: kernelOSVer = 0xA090100; break;
1123default:kernelOSVer = 0xA090100; break; //Last known kernel
1124}
1125break;
1126case 1: kernelOSVer = 0xA090100; break; // never exist (or released)
1127case 2: kernelOSVer = 0xA090200; break;
1128case 3: kernelOSVer = 0xA090300; break;
1129case 4: kernelOSVer = 0xA090400; break;
1130case 5: kernelOSVer = 0xA090500; break;
1131default:kernelOSVer = 0xA090500; break; //Last known kernel
1132}
1133break;
1134case 14:
1135switch (gDarwinMinor)
1136{
1137case 0: kernelOSVer = 0xA0A0000; break; // same kernel of 10.10.1
1138case 1: kernelOSVer = 0xA0A0100; break; // same kernel of 10.10
1139case 2: kernelOSVer = 0xA0A0200; break;
1140case 3: kernelOSVer = 0xA0A0300; break;
1141case 4: kernelOSVer = 0xA0A0400; break;
1142case 5: kernelOSVer = 0xA0A0500; break;
1143default:kernelOSVer = 0xA0A0500; break; //Last known kernel
1144}
1145break;
1146case 15: /* El Capitan */
1147switch (gDarwinMinor)
1148{
1149case 0: kernelOSVer = 0xA0B0000; break;
1150case 1: kernelOSVer = 0xA0B0100; break;
1151case 2: kernelOSVer = 0xA0B0200; break;
1152case 3: kernelOSVer = 0xA0B0300; break;
1153case 4: kernelOSVer = 0xA0B0400; break;
1154case 5: kernelOSVer = 0xA0B0500; break;
1155case 6: kernelOSVer = 0xA0B0600; break;
1156default:kernelOSVer = 0xA0B0600; break; //Last known kernel (add here updates)
1157}
1158break;
1159case 16: /* Sierra */
1160switch (gDarwinMinor)
1161{
1162case 0: kernelOSVer = 0xA0C0000; break;
1163case 1: kernelOSVer = 0xA0C0100; break;
1164case 2: kernelOSVer = 0xA0C0200; break;
1165case 3: kernelOSVer = 0xA0C0200; break;
1166case 4: kernelOSVer = 0xA0C0300; break;
1167case 5: kernelOSVer = 0xA0C0400; break;
1168case 6: kernelOSVer = 0xA0C0500; break;
1169case 7: kernelOSVer = 0xA0C0600; break;
1170//case 8: kernelOSVer = 0xA0C0700; break;
1171default:kernelOSVer = 0xA0C0600; break; //Last known kernel (add here updates)
1172}
1173break;
1174case 17: /* High Sierra */
1175switch (gDarwinMinor)
1176{
1177case 0: kernelOSVer = 0xA0D0000; break;
1178case 1: kernelOSVer = 0xA0D0100; break;
1179//case 2: kernelOSVer = 0xA0D0200; break; // 17.2.0
1180//case 3: kernelOSVer = 0xA0C0200; break;
1181//case 4: kernelOSVer = 0xA0C0300; break;
1182//case 5: kernelOSVer = 0xA0C0400; break;
1183//case 6: kernelOSVer = 0xA0C0500; break;
1184//case 7: kernelOSVer = 0xA0C0600; break;
1185//case 8: kernelOSVer = 0xA0C0700; break;
1186default:kernelOSVer = 0xA0D0100; break; //Last known kernel (add here updates)
1187}
1188break;
1189default:
1190kernelOSVer = 0xA0D0100;
1191break; //Last known kernel is Sierra 10.13.1
1192}
1193}
1194else
1195{
1196switch (MacOSVerCurrent)
1197{
1198// Snow
1199case 0xA060000: gDarwinMajor = 10; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.6
1200case 0xA060100: gDarwinMajor = 10; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.6.1
1201case 0xA060200: gDarwinMajor = 10; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.6.2
1202case 0xA060300: gDarwinMajor = 10; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.6.3
1203case 0xA060400: gDarwinMajor = 10; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.6.4
1204case 0xA060500: gDarwinMajor = 10; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.6.5
1205case 0xA060600: gDarwinMajor = 10; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.6.6
1206case 0xA060700: gDarwinMajor = 10; gDarwinMinor = 7; gDarwinRev = 0; break; // 10.6.7
1207case 0xA060800: gDarwinMajor = 10; gDarwinMinor = 8; gDarwinRev = 0; break; // 10.6.8
1208// Lion
1209case 0xA070000: gDarwinMajor = 11; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.7
1210case 0xA070100: gDarwinMajor = 11; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.7.1
1211case 0xA070200: gDarwinMajor = 11; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.7.2
1212case 0xA070300: gDarwinMajor = 11; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.7.3
1213case 0xA070400: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.7.4
1214case 0xA070500: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 2; break; // 10.7.5
1215// ML
1216case 0xA080000: gDarwinMajor = 12; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.8
1217case 0xA080100: gDarwinMajor = 12; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.8.1
1218case 0xA080200: gDarwinMajor = 12; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.8.2
1219case 0xA080300: gDarwinMajor = 12; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.8.3
1220case 0xA080400: gDarwinMajor = 12; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.8.4
1221case 0xA080500: gDarwinMajor = 12; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.8.5
1222// Mavericks
1223case 0xA090000: gDarwinMajor = 13; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.9
1224case 0xA090100: gDarwinMajor = 13; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.9.1
1225case 0xA090200: gDarwinMajor = 13; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.9.2
1226case 0xA090300: gDarwinMajor = 13; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.9.3
1227case 0xA090400: gDarwinMajor = 13; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.9.4
1228case 0xA090500: gDarwinMajor = 13; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.9.5
1229// Yosemite
1230case 0xA0A0000: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10
1231case 0xA0A0100: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10.1
1232case 0xA0A0200: gDarwinMajor = 14; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.10.2
1233case 0xA0A0300: gDarwinMajor = 14; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.10.3
1234case 0xA0A0400: gDarwinMajor = 14; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.10.4
1235case 0xA0A0500: gDarwinMajor = 14; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.10.5
1236// El Capitan
1237case 0xA0B0000: gDarwinMajor = 15; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.11
1238case 0xA0B0100: gDarwinMajor = 15; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.11.1
1239case 0xA0B0200: gDarwinMajor = 15; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.11.2
1240case 0xA0B0300: gDarwinMajor = 15; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.11.3
1241case 0xA0B0400: gDarwinMajor = 15; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.11.4
1242case 0xA0B0500: gDarwinMajor = 15; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.11.5
1243case 0xA0B0600: gDarwinMajor = 15; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.11.6
1244// Sierra
1245case 0xA0C0000: gDarwinMajor = 16; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.12
1246case 0xA0C0100: gDarwinMajor = 16; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.12.1
1247case 0xA0C0200: gDarwinMajor = 16; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.12.2
1248case 0xA0C0300: gDarwinMajor = 16; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.12.3
1249case 0xA0C0400: gDarwinMajor = 16; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.12.4
1250case 0xA0C0500: gDarwinMajor = 16; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.12.5
1251case 0xA0C0600: gDarwinMajor = 16; gDarwinMinor = 7; gDarwinRev = 0; break; // 10.12.6
1252//case 0xA0C0700: gDarwinMajor = 16; gDarwinMinor = x; gDarwinRev = x; break; // 10.12.7
1253// High Sierra
1254case 0xA0D0000: gDarwinMajor = 17; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.13
1255case 0xA0D0100: gDarwinMajor = 17; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.13.1
1256// Mojave
1257
1258// default = last known kernel
1259default: gDarwinMajor = 17; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.13.1;
1260}
1261}
1262
1263// Notify modules that the kernel has been decompressed, thinned and is about to be decoded
1264execute_hook("DecodeKernel", (void *)binary, NULL, NULL, NULL);
1265
1266/* ================================================================ */
1267
1268ret = DecodeMachO(binary, rentry, raddr, rsize);
1269if (ret < 0 && archCpuType == CPU_TYPE_X86_64)
1270{
1271archCpuType = CPU_TYPE_I386;
1272ret = DecodeMachO(binary, rentry, raddr, rsize);
1273}
1274
1275return ret;
1276}
1277

Archive Download this file

Revision: 2918