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

Archive Download this file

Revision: 1804