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

Archive Download this file

Revision: 2858