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;
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
1003useDarwinVersion = true;
1004uint32_t offset = 0;
1005strncpy(gDarwinBuildVerStr, "Darwin Kernel Version", sizeof(gDarwinBuildVerStr));
1006
1007while ((offset < 0xFFFFFFFF - (uint32_t)binary - 256) && memcmp(binary + offset, gDarwinBuildVerStr, 21))
1008{
1009offset++;
1010}
1011if (offset < 0xFFFFFFFF - (uint32_t)binary - 256)
1012{
1013strncpy(gDarwinBuildVerStr, (char *)(binary + offset), sizeof(gDarwinBuildVerStr));
1014}
1015else
1016{
1017strcat(gDarwinBuildVerStr, ": Unknown");
1018useDarwinVersion = false;
1019}
1020// Micky1979 use Bungo gDarwinBuildVerStr and split into gDarwinMajor, gDarwinMinor and gDarwinRev
1021if (useDarwinVersion)
1022{
1023useDarwinVersion = false;
1024const char *pattern = strstr(gDarwinBuildVerStr, "Darwin Kernel Version ")+22;
1025const char *until = strstr(pattern, ":");
1026size_t vlen = until - pattern;
1027char *ver = (char *)malloc(sizeof(char)*(len+1));
1028strncpy(ver, pattern, vlen);
1029ver[vlen] = '\0';
1030char *delim;
1031char *temp;
1032gDarwinMajor = -1; gDarwinMinor = -1; gDarwinRev = -1;
1033if (ver != NULL)
1034{
1035temp = ver;
1036int count = 1;
1037while ((delim = strsep_c(&ver, ".")) != NULL)
1038{
1039switch (count)
1040{
1041case 1: gDarwinMajor = atoi(delim); break;
1042case 2: gDarwinMinor = atoi(delim); break;
1043case 3: gDarwinRev = atoi(delim); break;
1044default: break;
1045}
1046count ++;
1047}
1048free(temp);
1049}
1050
1051if (gDarwinMajor >= 0 && gDarwinMinor >= 0 && gDarwinRev >= 0)
1052{
1053useDarwinVersion = true;
1054}
1055
1056switch (gDarwinMajor)
1057{
1058case 10:
1059switch (gDarwinMinor)
1060{
1061case 0: kernelOSVer = 0xA060000; break;
1062case 1: kernelOSVer = 0xA060100; break;
1063case 2: kernelOSVer = 0xA060200; break;
1064case 3: kernelOSVer = 0xA060300; break;
1065case 4: kernelOSVer = 0xA060400; break;
1066case 5: kernelOSVer = 0xA060500; break;
1067case 6: kernelOSVer = 0xA060600; break;
1068case 7: kernelOSVer = 0xA060700; break;
1069case 8: kernelOSVer = 0xA060800; break;
1070default:kernelOSVer = 0xA060800; break; //Last known kernel
1071}
1072break;
1073case 11:
1074switch (gDarwinMinor)
1075{
1076case 0: kernelOSVer = 0xA070000; break;
1077case 1: kernelOSVer = 0xA070100; break;
1078case 2: kernelOSVer = 0xA070200; break;
1079case 3: kernelOSVer = 0xA070300; break;
1080case 4:
1081switch (gDarwinRev)
1082{
1083case 0: kernelOSVer = 0xA070400; break;
1084case 1: kernelOSVer = 0xA070400; break;
1085case 2: kernelOSVer = 0xA070500; break;
1086default:kernelOSVer = 0xA070500; break; //Last known kernel
1087}
1088default:kernelOSVer = 0xA070500; break; //Last known kernel
1089}
1090break;
1091case 12:
1092switch (gDarwinMinor)
1093{
1094case 0: kernelOSVer = 0xA080000; break;
1095case 1: kernelOSVer = 0xA080100; break;
1096case 2: kernelOSVer = 0xA080200; break;
1097case 3: kernelOSVer = 0xA080300; break;
1098case 4: kernelOSVer = 0xA080400; break;
1099case 5: kernelOSVer = 0xA080500; break; // 10.8.5
1100case 6: kernelOSVer = 0xA080500; break; // 10.8.5 update
1101default:kernelOSVer = 0xA080500; break; //Last known kernel
1102}
1103break;
1104case 13:
1105switch (gDarwinMinor)
1106{
1107case 0: kernelOSVer = 0xA090000;
1108switch (gDarwinRev)
1109{
1110case 0: kernelOSVer = 0xA090000; break;
1111case 1: kernelOSVer = 0xA090000; break; // never exist (or released)
1112case 2: kernelOSVer = 0xA090100; break;
1113default:kernelOSVer = 0xA090100; break; //Last known kernel
1114}
1115break;
1116case 1: kernelOSVer = 0xA090100; break; // never exist (or released)
1117case 2: kernelOSVer = 0xA090200; break;
1118case 3: kernelOSVer = 0xA090300; break;
1119case 4: kernelOSVer = 0xA090400; break;
1120case 5: kernelOSVer = 0xA090500; break;
1121default:kernelOSVer = 0xA090500; break; //Last known kernel
1122}
1123break;
1124case 14:
1125switch (gDarwinMinor)
1126{
1127case 0: kernelOSVer = 0xA0A0000; break; // same kernel of 10.10.1
1128case 1: kernelOSVer = 0xA0A0100; break; // same kernel of 10.10
1129case 2: kernelOSVer = 0xA0A0200; break;
1130case 3: kernelOSVer = 0xA0A0300; break;
1131case 4: kernelOSVer = 0xA0A0400; break;
1132case 5: kernelOSVer = 0xA0A0500; break;
1133default:kernelOSVer = 0xA0A0500; break; //Last known kernel
1134}
1135break;
1136case 15: /* El Capitan */
1137switch (gDarwinMinor)
1138{
1139case 0: kernelOSVer = 0xA0B0000; break;
1140case 1: kernelOSVer = 0xA0B0100; break;
1141case 2: kernelOSVer = 0xA0B0200; break;
1142case 3: kernelOSVer = 0xA0B0300; break;
1143case 4: kernelOSVer = 0xA0B0400; break;
1144case 5: kernelOSVer = 0xA0B0500; break;
1145case 6: kernelOSVer = 0xA0B0600; break;
1146default:kernelOSVer = 0xA0B0600; break; //Last known kernel (add here updates)
1147}
1148break;
1149case 16: /* Sierra */
1150switch (gDarwinMinor)
1151{
1152case 0: kernelOSVer = 0xA0C0000; break;
1153case 1: kernelOSVer = 0xA0C0100; break;
1154case 2: kernelOSVer = 0xA0C0200; break;
1155case 3: kernelOSVer = 0xA0C0200; break;
1156case 4: kernelOSVer = 0xA0C0300; break;
1157case 5: kernelOSVer = 0xA0C0400; break;
1158case 6: kernelOSVer = 0xA0C0500; break;
1159case 7: kernelOSVer = 0xA0C0600; break;
1160//case 8: kernelOSVer = 0xA0C0700; break;
1161default:kernelOSVer = 0xA0C0600; break; //Last known kernel (add here updates)
1162}
1163break;
1164case 17: /* High Sierra */
1165switch (gDarwinMinor)
1166{
1167case 0: kernelOSVer = 0xA0D0000; break;
1168case 1: kernelOSVer = 0xA0D0100; break;
1169//case 2: kernelOSVer = 0xA0D0200; break; // 17.2.0
1170//case 3: kernelOSVer = 0xA0C0200; break;
1171//case 4: kernelOSVer = 0xA0C0300; break;
1172//case 5: kernelOSVer = 0xA0C0400; break;
1173//case 6: kernelOSVer = 0xA0C0500; break;
1174//case 7: kernelOSVer = 0xA0C0600; break;
1175//case 8: kernelOSVer = 0xA0C0700; break;
1176default:kernelOSVer = 0xA0D0100; break; //Last known kernel (add here updates)
1177}
1178break;
1179default:
1180kernelOSVer = 0xA0D0100;
1181break; //Last known kernel is Sierra 10.13.1
1182}
1183}
1184else
1185{
1186switch (MacOSVerCurrent)
1187{
1188// Snow
1189case 0xA060000: gDarwinMajor = 10; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.6
1190case 0xA060100: gDarwinMajor = 10; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.6.1
1191case 0xA060200: gDarwinMajor = 10; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.6.2
1192case 0xA060300: gDarwinMajor = 10; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.6.3
1193case 0xA060400: gDarwinMajor = 10; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.6.4
1194case 0xA060500: gDarwinMajor = 10; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.6.5
1195case 0xA060600: gDarwinMajor = 10; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.6.6
1196case 0xA060700: gDarwinMajor = 10; gDarwinMinor = 7; gDarwinRev = 0; break; // 10.6.7
1197case 0xA060800: gDarwinMajor = 10; gDarwinMinor = 8; gDarwinRev = 0; break; // 10.6.8
1198// Lion
1199case 0xA070000: gDarwinMajor = 11; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.7
1200case 0xA070100: gDarwinMajor = 11; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.7.1
1201case 0xA070200: gDarwinMajor = 11; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.7.2
1202case 0xA070300: gDarwinMajor = 11; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.7.3
1203case 0xA070400: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.7.4
1204case 0xA070500: gDarwinMajor = 11; gDarwinMinor = 4; gDarwinRev = 2; break; // 10.7.5
1205// ML
1206case 0xA080000: gDarwinMajor = 12; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.8
1207case 0xA080100: gDarwinMajor = 12; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.8.1
1208case 0xA080200: gDarwinMajor = 12; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.8.2
1209case 0xA080300: gDarwinMajor = 12; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.8.3
1210case 0xA080400: gDarwinMajor = 12; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.8.4
1211case 0xA080500: gDarwinMajor = 12; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.8.5
1212// Mavericks
1213case 0xA090000: gDarwinMajor = 13; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.9
1214case 0xA090100: gDarwinMajor = 13; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.9.1
1215case 0xA090200: gDarwinMajor = 13; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.9.2
1216case 0xA090300: gDarwinMajor = 13; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.9.3
1217case 0xA090400: gDarwinMajor = 13; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.9.4
1218case 0xA090500: gDarwinMajor = 13; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.9.5
1219// Yosemite
1220case 0xA0A0000: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10
1221case 0xA0A0100: gDarwinMajor = 14; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.10.1
1222case 0xA0A0200: gDarwinMajor = 14; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.10.2
1223case 0xA0A0300: gDarwinMajor = 14; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.10.3
1224case 0xA0A0400: gDarwinMajor = 14; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.10.4
1225case 0xA0A0500: gDarwinMajor = 14; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.10.5
1226// El Capitan
1227case 0xA0B0000: gDarwinMajor = 15; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.11
1228case 0xA0B0100: gDarwinMajor = 15; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.11.1
1229case 0xA0B0200: gDarwinMajor = 15; gDarwinMinor = 2; gDarwinRev = 0; break; // 10.11.2
1230case 0xA0B0300: gDarwinMajor = 15; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.11.3
1231case 0xA0B0400: gDarwinMajor = 15; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.11.4
1232case 0xA0B0500: gDarwinMajor = 15; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.11.5
1233case 0xA0B0600: gDarwinMajor = 15; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.11.6
1234// Sierra
1235case 0xA0C0000: gDarwinMajor = 16; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.12
1236case 0xA0C0100: gDarwinMajor = 16; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.12.1
1237case 0xA0C0200: gDarwinMajor = 16; gDarwinMinor = 3; gDarwinRev = 0; break; // 10.12.2
1238case 0xA0C0300: gDarwinMajor = 16; gDarwinMinor = 4; gDarwinRev = 0; break; // 10.12.3
1239case 0xA0C0400: gDarwinMajor = 16; gDarwinMinor = 5; gDarwinRev = 0; break; // 10.12.4
1240case 0xA0C0500: gDarwinMajor = 16; gDarwinMinor = 6; gDarwinRev = 0; break; // 10.12.5
1241case 0xA0C0600: gDarwinMajor = 16; gDarwinMinor = 7; gDarwinRev = 0; break; // 10.12.6
1242//case 0xA0C0700: gDarwinMajor = 16; gDarwinMinor = x; gDarwinRev = x; break; // 10.12.7
1243// High Sierra
1244case 0xA0D0000: gDarwinMajor = 17; gDarwinMinor = 0; gDarwinRev = 0; break; // 10.13
1245case 0xA0D0100: gDarwinMajor = 17; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.13.1
1246
1247// default = last known kernel
1248default: gDarwinMajor = 17; gDarwinMinor = 1; gDarwinRev = 0; break; // 10.13.1;
1249}
1250}
1251
1252// Notify modules that the kernel has been decompressed, thinned and is about to be decoded
1253execute_hook("DecodeKernel", (void *)binary, NULL, NULL, NULL);
1254
1255/* ================================================================ */
1256
1257ret = DecodeMachO(binary, rentry, raddr, rsize);
1258if (ret < 0 && archCpuType == CPU_TYPE_X86_64)
1259{
1260archCpuType = CPU_TYPE_I386;
1261ret = DecodeMachO(binary, rentry, raddr, rsize);
1262}
1263
1264return ret;
1265}
1266

Archive Download this file

Revision: 2906