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

Archive Download this file

Revision: 2871