Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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 "drivers.h"
41#include "modules.h"
42
43extern char gMacOSVersion[];
44extern char gBootKernelCacheFile[];
45long FileLoadDrivers(char *dirSpec, long plugin);
46#ifdef NBP_SUPPORT
47long NetLoadDrivers(char *dirSpec);
48#endif
49long LoadDriverMKext(char *fileSpec);
50long LoadDriverPList(char *dirSpec, char *name, long bundleType);
51long LoadMatchedModules(void);
52#if UNUSED
53long MatchPersonalities(void);
54#endif
55long MatchLibraries(void);
56
57static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities);
58long InitDriverSupport(void);
59
60static ModulePtr gModuleHead, gModuleTail;
61static TagPtr gPersonalityHead, gPersonalityTail;
62char * gExtensionsSpec;
63char * gDriverSpec;
64char * gFileSpec;
65char * gTempSpec;
66char * gFileName;
67
68//==========================================================================
69// InitDriverSupport
70
71long
72InitDriverSupport( void )
73{
74 gExtensionsSpec = malloc( 4096 );
75 gDriverSpec = malloc( 4096 );
76 gFileSpec = malloc( 4096 );
77 gTempSpec = malloc( 4096 );
78 gFileName = malloc( 4096 );
79
80 if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
81 stop("InitDriverSupport error");
82
83 return 0;
84}
85
86//==========================================================================
87// LoadDrivers
88
89long LoadDrivers( char * dirSpec )
90{
91 char dirSpecExtra[1024];
92
93 if ( InitDriverSupport() != 0 )
94 return 0;
95
96
97
98 // Load extra drivers if a hook has been installed.
99
100int step = 0;
101execute_hook("ramDiskLoadDrivers", &step, NULL, NULL, NULL, NULL, NULL);
102#ifdef NBP_SUPPORT
103 if ( gBootFileType == kNetworkDeviceType )
104 {
105 if (NetLoadDrivers(dirSpec) != 0) {
106 error("Could not load drivers from the network\n");
107 return -1;
108 }
109 }
110 else
111#endif
112if ( gBootFileType == kBlockDeviceType )
113{
114// First try to load Extra extensions from the ramdisk if isn't aliased as bt(0,0).
115#ifndef OPTION_ROM
116// First try a specfic OS version folder ie 10.5
117
118step = 1;
119execute_hook("ramDiskLoadDrivers", &step, NULL, NULL, NULL, NULL, NULL);
120
121#endif
122
123// First try a specfic OS version folder ie 10.5
124sprintf(dirSpecExtra, "/Extra/%s/", &gMacOSVersion);
125if (FileLoadDrivers(dirSpecExtra, 0) != 0)
126{
127// Next try to load Extra extensions from the selected root partition.
128strcpy(dirSpecExtra, "/Extra/");
129if (FileLoadDrivers(dirSpecExtra, 0) != 0)
130{
131// If failed, then try to load Extra extensions from the boot partition
132// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
133if (!(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no))
134{
135// First try a specfic OS version folder ie 10.5
136sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion);
137if (FileLoadDrivers(dirSpecExtra, 0) != 0)
138{
139// Next we'll try the base
140strcpy(dirSpecExtra, "bt(0,0)/Extra/");
141FileLoadDrivers(dirSpecExtra, 0);
142}
143}
144#ifndef OPTION_ROM
145step = 2;
146execute_hook("ramDiskLoadDrivers", &step, NULL, NULL, NULL, NULL, NULL);
147#endif
148}
149
150}
151#ifdef BOOT_HELPER_SUPPORT
152// TODO: fix this, the order does matter, and it's not correct now.
153// Also try to load Extensions from boot helper partitions.
154if (gBootVolume->flags & kBVFlagBooter)
155{
156strcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/");
157if (FileLoadDrivers(dirSpecExtra, 0) != 0)
158{
159strcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/");
160if (FileLoadDrivers(dirSpecExtra, 0) != 0)
161{
162strcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/");
163FileLoadDrivers(dirSpecExtra, 0);
164}
165}
166}
167#endif
168
169if (gMKextName[0] != '\0')
170{
171verbose("LoadDrivers: Loading from [%s]\n", gMKextName);
172if ( LoadDriverMKext(gMKextName) != 0 )
173{
174error("Could not load %s\n", gMKextName);
175return -1;
176}
177}
178else
179{
180strcpy(gExtensionsSpec, dirSpec);
181strcat(gExtensionsSpec, "System/Library/");
182FileLoadDrivers(gExtensionsSpec, 0);
183}
184}
185else
186{
187return 0;
188}
189#if UNUSED
190 MatchPersonalities();
191#endif
192
193 MatchLibraries();
194
195 LoadMatchedModules();
196
197 return 0;
198}
199
200//==========================================================================
201// FileLoadMKext
202
203static long
204FileLoadMKext( const char * dirSpec, const char * extDirSpec )
205{
206long ret, flags, time, time2;
207char altDirSpec[512];
208
209sprintf (altDirSpec, "%s%s", dirSpec, extDirSpec);
210ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
211if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
212{
213ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
214if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeDirectory) ||
215(((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
216{
217sprintf(gDriverSpec, "%sExtensions.mkext", altDirSpec);
218verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec);
219if (LoadDriverMKext(gDriverSpec) == 0) return 0;
220}
221}
222return -1;
223}
224
225//==========================================================================
226// FileLoadDrivers
227
228long
229FileLoadDrivers( char * dirSpec, long plugin )
230{
231 long ret, length, flags, time, bundleType;
232 long long index;
233 long result = -1;
234 const char * name;
235
236 if ( !plugin )
237 {
238 // First try 10.6's path for loading Extensions.mkext.
239 if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0)
240return 0;
241
242 // Next try the legacy path.
243 else if (FileLoadMKext(dirSpec, "") == 0)
244return 0;
245
246 strcat(dirSpec, "Extensions");
247 }
248
249 index = 0;
250 while (1) {
251 ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
252 if (ret == -1) break;
253
254 // Make sure this is a directory.
255 if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
256
257 // Make sure this is a kext.
258 length = strlen(name);
259 if (strcmp(name + length - 5, ".kext")) continue;
260
261 // Save the file name.
262 strcpy(gFileName, name);
263
264 // Determine the bundle type.
265 sprintf(gTempSpec, "%s/%s", dirSpec, gFileName);
266 ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
267 if (ret == 0) bundleType = kCFBundleType2;
268 else bundleType = kCFBundleType3;
269
270 if (!plugin)
271 sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName,
272 (bundleType == kCFBundleType2) ? "Contents/" : "");
273
274 ret = LoadDriverPList(dirSpec, gFileName, bundleType);
275
276 if (result != 0)
277result = ret;
278
279 if (!plugin)
280FileLoadDrivers(gDriverSpec, 1);
281 }
282
283 return result;
284}
285
286//==========================================================================
287//
288#ifdef NBP_SUPPORT
289long
290NetLoadDrivers( char * dirSpec )
291{
292 long tries;
293
294#if NODEF
295 long cnt;
296
297 // Get the name of the kernel
298 cnt = strlen(gBootFile);
299 while (cnt--) {
300 if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ',')) {
301cnt++;
302break;
303 }
304 }
305#endif
306
307 // INTEL modification
308 sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile);
309
310 verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
311
312 tries = 3;
313 while (tries--)
314 {
315 if (LoadDriverMKext(gDriverSpec) == 0) break;
316 }
317 if (tries == -1) return -1;
318
319 return 0;
320}
321#endif
322//==========================================================================
323// loadDriverMKext
324
325long
326LoadDriverMKext( char * fileSpec )
327{
328 unsigned long driversAddr, driversLength;
329 long length;
330 char segName[32];
331 DriversPackage * package;
332
333#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
334
335 // Load the MKext.
336 length = LoadThinFatFile(fileSpec, (void **)&package);
337 if (!length || (unsigned)length < sizeof (DriversPackage)) return -1;
338
339// call hook to notify modules that the mkext has been loaded
340execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) length, NULL, NULL, NULL);
341
342
343 // Verify the MKext.
344 if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
345 ( GetPackageElement(signature2) != kDriverPackageSignature2) ||
346 ( GetPackageElement(length) > kLoadSize ) ||
347 ( GetPackageElement(alder32) !=
348 local_adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
349 {
350 return -1;
351 }
352
353
354 // Make space for the MKext.
355 driversLength = GetPackageElement(length);
356 driversAddr = AllocateKernelMemory(driversLength);
357
358 // Copy the MKext.
359 memcpy((void *)driversAddr, (void *)package, driversLength);
360
361 // Add the MKext to the memory map.
362 sprintf(segName, "DriversPackage-%lx", driversAddr);
363
364#if UNUSED
365 AllocateMemoryRange(segName, driversAddr, driversLength,
366 kBootDriverTypeMKEXT);
367#else
368 AllocateMemoryRange(segName, driversAddr, driversLength);
369#endif
370
371 return 0;
372}
373
374//==========================================================================
375// LoadDriverPList
376
377long
378LoadDriverPList( char * dirSpec, char * name, long bundleType )
379{
380 long length, executablePathLength, bundlePathLength;
381 ModulePtr module;
382 TagPtr personalities;
383 char * buffer = 0;
384 char * tmpExecutablePath = 0;
385 char * tmpBundlePath = 0;
386 long ret = -1;
387
388 do {
389 // Save the driver path.
390
391 sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
392 (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
393 executablePathLength = strlen(gFileSpec) + 1;
394
395 tmpExecutablePath = malloc(executablePathLength);
396 if (tmpExecutablePath == 0) break;
397
398 strcpy(tmpExecutablePath, gFileSpec);
399
400 sprintf(gFileSpec, "%s/%s", dirSpec, name);
401 bundlePathLength = strlen(gFileSpec) + 1;
402
403 tmpBundlePath = malloc(bundlePathLength);
404 if (tmpBundlePath == 0) break;
405
406 strcpy(tmpBundlePath, gFileSpec);
407
408 // Construct the file spec to the plist, then load it.
409
410 sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
411 (bundleType == kCFBundleType2) ? "Contents/" : "");
412
413 length = LoadFile(gFileSpec);
414 if (length == -1) break;
415
416 length = length + 1;
417 buffer = malloc(length);
418 if (buffer == 0) break;
419
420 strlcpy(buffer, (char *)kLoadAddr, length);
421
422 // Parse the plist.
423
424 ret = ParseXML(buffer, &module, &personalities);
425 if (ret != 0) { break; }
426
427 // Allocate memory for the driver path and the plist.
428
429 module->executablePath = tmpExecutablePath;
430 module->bundlePath = tmpBundlePath;
431 module->bundlePathLength = bundlePathLength;
432 module->plistAddr = malloc(length);
433
434 if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
435 break;
436
437 // Save the driver path in the module.
438 //strcpy(module->driverPath, tmpDriverPath);
439 tmpExecutablePath = 0;
440 tmpBundlePath = 0;
441
442 // Add the plist to the module.
443
444 strlcpy(module->plistAddr, (char *)kLoadAddr, length);
445 module->plistLength = length;
446
447 // Add the module to the end of the module list.
448
449 if (gModuleHead == 0)
450 gModuleHead = module;
451 else
452 gModuleTail->nextModule = module;
453 gModuleTail = module;
454
455 // Add the persionalities to the personality list.
456
457 if (personalities) personalities = personalities->tag;
458 while (personalities != 0)
459 {
460 if (gPersonalityHead == 0)
461 gPersonalityHead = personalities->tag;
462 else
463 gPersonalityTail->tagNext = personalities->tag;
464
465 gPersonalityTail = personalities->tag;
466 personalities = personalities->tagNext;
467 }
468
469 ret = 0;
470 }
471 while (0);
472
473 if ( buffer ) free( buffer );
474 if ( tmpExecutablePath ) free( tmpExecutablePath );
475 if ( tmpBundlePath ) free( tmpBundlePath );
476
477 return ret;
478}
479
480
481//==========================================================================
482// LoadMatchedModules
483
484long LoadMatchedModules( void )
485{
486 TagPtr prop;
487 ModulePtr module;
488 char *fileName, segName[32];
489 DriverInfoPtr driver;
490 long length, driverAddr, driverLength;
491 void *executableAddr = 0;
492
493
494 module = gModuleHead;
495
496 while (module != 0)
497 {
498 if (module->willLoad)
499 {
500 prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
501
502 if (prop != 0)
503 {
504 fileName = prop->string;
505 sprintf(gFileSpec, "%s%s", module->executablePath, fileName);
506 length = LoadThinFatFile(gFileSpec, &executableAddr);
507if (length == 0)
508{
509length = LoadFile(gFileSpec);
510executableAddr = (void *)kLoadAddr;
511}
512 //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc();
513 }
514 else
515 length = 0;
516
517 if (length != -1)
518 {
519//driverModuleAddr = (void *)kLoadAddr;
520 //if (length != 0)
521 //{
522// ThinFatFile(&driverModuleAddr, &length);
523//}
524
525 // Make make in the image area.
526
527execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL, NULL, NULL);
528
529 driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
530 driverAddr = AllocateKernelMemory(driverLength);
531
532 // Set up the DriverInfo.
533 driver = (DriverInfoPtr)driverAddr;
534 driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
535 driver->plistLength = module->plistLength;
536 if (length != 0)
537 {
538 driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
539 module->plistLength);
540 driver->executableLength = length;
541 }
542 else
543 {
544 driver->executableAddr = 0;
545 driver->executableLength = 0;
546 }
547 driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
548 module->plistLength + driver->executableLength);
549 driver->bundlePathLength = module->bundlePathLength;
550
551 // Save the plist, module and bundle.
552 strcpy(driver->plistAddr, module->plistAddr);
553 if (length != 0)
554 {
555 memcpy(driver->executableAddr, executableAddr, length);
556 }
557 strcpy(driver->bundlePathAddr, module->bundlePath);
558
559 // Add an entry to the memory map.
560 sprintf(segName, "Driver-%lx", (unsigned long)driver);
561#if UNUSED
562 AllocateMemoryRange(segName, driverAddr, driverLength,
563 kBootDriverTypeKEXT);
564#else
565 AllocateMemoryRange(segName, driverAddr, driverLength);
566#endif
567
568 }
569 }
570 module = module->nextModule;
571 }
572
573 return 0;
574}
575
576#if UNUSED
577//==========================================================================
578// MatchPersonalities
579
580long MatchPersonalities( void )
581{
582 /* IONameMatch support not implemented */
583 return 0;
584}
585#endif
586
587//==========================================================================
588// MatchLibraries
589
590long MatchLibraries( void )
591{
592 TagPtr prop, prop2;
593 ModulePtr module, module2;
594 long done;
595
596 do {
597 done = 1;
598 module = gModuleHead;
599
600 while (module != 0)
601 {
602 if (module->willLoad == 1)
603 {
604 prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
605 if (prop != 0)
606 {
607 prop = prop->tag;
608 while (prop != 0)
609 {
610 module2 = gModuleHead;
611 while (module2 != 0)
612 {
613 prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
614 if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
615 {
616 if (module2->willLoad == 0) module2->willLoad = 1;
617 break;
618 }
619 module2 = module2->nextModule;
620 }
621 prop = prop->tagNext;
622 }
623 }
624 module->willLoad = 2;
625 done = 0;
626 }
627 module = module->nextModule;
628 }
629 }
630 while (!done);
631
632 return 0;
633}
634
635
636//==========================================================================
637// FindModule
638
639#if UNUSED
640static ModulePtr
641FindModule( char * name )
642{
643 ModulePtr module;
644 TagPtr prop;
645
646 module = gModuleHead;
647
648 while (module != 0)
649 {
650 prop = GetProperty(module->dict, kPropCFBundleIdentifier);
651 if ((prop != 0) && !strcmp(name, prop->string)) break;
652 module = module->nextModule;
653 }
654
655 return module;
656}
657#endif
658
659//==========================================================================
660// ParseXML
661
662static long
663ParseXML( char * buffer, ModulePtr * module, TagPtr * personalities )
664{
665long length, pos;
666TagPtr moduleDict, required;
667ModulePtr tmpModule;
668
669 pos = 0;
670
671 while (1)
672 {
673 length = XMLParseNextTag(buffer + pos, &moduleDict);
674 if (length == -1) break;
675
676 pos += length;
677
678 if (moduleDict == 0) continue;
679 if (moduleDict->type == kTagTypeDict) break;
680
681 XMLFreeTag(moduleDict);
682 }
683
684 if (length == -1) return -1;
685
686 required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
687 if ( (required == 0) ||
688(required->type != kTagTypeString) ||
689!strcmp(required->string, "Safe Boot"))
690 {
691 XMLFreeTag(moduleDict);
692 return -2;
693 }
694
695 tmpModule = malloc(sizeof(Module));
696 if (tmpModule == 0)
697 {
698 XMLFreeTag(moduleDict);
699 return -1;
700 }
701 tmpModule->dict = moduleDict;
702
703 // For now, load any module that has OSBundleRequired != "Safe Boot".
704
705 tmpModule->willLoad = 1;
706
707 *module = tmpModule;
708
709 // Get the personalities.
710
711 *personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
712
713 return 0;
714}
715
716
717long
718DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
719{
720 long ret;
721 compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary;
722 u_int32_t uncompressed_size, size;
723 void *buffer;
724unsigned long len;
725
726#if 0
727 printf("kernel header:\n");
728 printf("signature: 0x%x\n", kernel_header->signature);
729 printf("compress_type: 0x%x\n", kernel_header->compress_type);
730 printf("adler32: 0x%x\n", kernel_header->adler32);
731 printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
732 printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
733 getc();
734#endif
735
736
737 if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) {
738 if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) {
739 error("kernel compression is bad\n");
740 return -1;
741 }
742
743 uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
744 binary = buffer = malloc(uncompressed_size);
745
746 size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0],
747 OSSwapBigToHostInt32(kernel_header->compressed_size));
748 if (uncompressed_size != size) {
749 error("size mismatch from lzss: %x\n", size);
750 return -1;
751 }
752 if (OSSwapBigToHostInt32(kernel_header->adler32) !=
753 local_adler32(binary, uncompressed_size)) {
754 printf("adler mismatch\n");
755 return -1;
756 }
757if (((gBootMode & kBootModeSafe) == 0) && (gBootKernelCacheFile[0] != '\0') && gMacOSVersion[3] == '7')
758bootInfo->adler32 = kernel_header->adler32;
759 }
760
761ret = ThinFatFile(&binary, &len);
762if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
763{
764archCpuType=CPU_TYPE_I386;
765ret = ThinFatFile(&binary, &len);
766}
767
768ret = DecodeMachO(binary, rentry, raddr, rsize);
769
770if (ret<0 && archCpuType==CPU_TYPE_X86_64)
771{
772archCpuType=CPU_TYPE_I386;
773ret = DecodeMachO(binary, rentry, raddr, rsize);
774}
775
776return ret;
777}

Archive Download this file

Revision: 1119