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

Archive Download this file

Revision: 1468