]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Portions Copyright (c) 1999 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 1.1 (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 | * Copyright 1993 NeXT, Inc. | |
26 | * All rights reserved. | |
27 | */ | |
28 | ||
29 | #include "libsaio.h" | |
30 | #include "kernBootStruct.h" | |
31 | #include "stringConstants.h" | |
14c7c974 A |
32 | #include "legacy/configTablePrivate.h" |
33 | ||
34 | extern KERNBOOTSTRUCT *kernBootStruct; | |
35 | extern char *Language; | |
36 | extern char *LoadableFamilies; | |
37 | ||
38 | static void eatThru(char val, char **table_p); | |
39 | ||
40 | static inline int isspace(char c) | |
41 | { | |
42 | return (c == ' ' || c == '\t'); | |
43 | } | |
44 | ||
45 | /* | |
46 | * Compare a string to a key with quoted characters | |
47 | */ | |
48 | static inline int | |
49 | keyncmp(char *str, char *key, int n) | |
50 | { | |
51 | int c; | |
52 | while (n--) { | |
53 | c = *key++; | |
54 | if (c == '\\') { | |
55 | switch(c = *key++) { | |
56 | case 'n': | |
57 | c = '\n'; | |
58 | break; | |
59 | case 'r': | |
60 | c = '\r'; | |
61 | break; | |
62 | case 't': | |
63 | c = '\t'; | |
64 | break; | |
65 | default: | |
66 | break; | |
67 | } | |
68 | } else if (c == '\"') { | |
69 | /* Premature end of key */ | |
70 | return 1; | |
71 | } | |
72 | if (c != *str++) { | |
73 | return 1; | |
74 | } | |
75 | } | |
76 | return 0; | |
77 | } | |
78 | ||
79 | static void eatThru(char val, char **table_p) | |
80 | { | |
81 | register char *table = *table_p; | |
82 | register BOOL found = NO; | |
83 | ||
84 | while (*table && !found) | |
85 | { | |
86 | if (*table == '\\') table += 2; | |
87 | else | |
88 | { | |
89 | if (*table == val) found = YES; | |
90 | table++; | |
91 | } | |
92 | } | |
93 | *table_p = table; | |
94 | } | |
95 | ||
96 | /* Remove key and its associated value from the table. */ | |
97 | ||
98 | BOOL | |
99 | removeKeyFromTable(const char *key, char *table) | |
100 | { | |
101 | register int len; | |
102 | register char *tab; | |
103 | char *buf; | |
104 | ||
105 | len = strlen(key); | |
106 | tab = (char *)table; | |
107 | buf = (char *)malloc(len + 3); | |
108 | ||
109 | sprintf(buf, "\"%s\"", key); | |
110 | len = strlen(buf); | |
111 | ||
112 | while(*tab) { | |
113 | if(strncmp(buf, tab, len) == 0) { | |
114 | char c; | |
115 | ||
116 | while((c = *(tab + len)) != ';') { | |
117 | if(c == 0) { | |
118 | len = -1; | |
119 | goto out; | |
120 | } | |
121 | len++; | |
122 | } | |
123 | len++; | |
124 | if(*(tab + len) == '\n') len++; | |
125 | goto out; | |
126 | } | |
127 | tab++; | |
128 | } | |
129 | len = -1; | |
130 | out: | |
131 | free(buf); | |
132 | ||
133 | if(len == -1) return NO; | |
134 | ||
135 | while((*tab = *(tab + len))) { | |
136 | tab++; | |
137 | } | |
138 | ||
139 | return YES; | |
140 | } | |
141 | ||
142 | char * | |
143 | newStringFromList( | |
144 | char **list, | |
145 | int *size | |
146 | ) | |
147 | { | |
148 | char *begin = *list, *end; | |
149 | char *newstr; | |
150 | int newsize = *size; | |
151 | ||
152 | while (*begin && newsize && isspace(*begin)) { | |
153 | begin++; | |
154 | newsize--; | |
155 | } | |
156 | end = begin; | |
157 | while (*end && newsize && !isspace(*end)) { | |
158 | end++; | |
159 | newsize--; | |
160 | } | |
161 | if (begin == end) | |
162 | return 0; | |
163 | newstr = malloc(end - begin + 1); | |
164 | strncpy(newstr, begin, end - begin); | |
165 | *list = end; | |
166 | *size = newsize; | |
167 | return newstr; | |
168 | } | |
169 | ||
170 | /* | |
171 | * compress == compress escaped characters to one character | |
172 | */ | |
173 | int stringLength(char *table, int compress) | |
174 | { | |
175 | int ret = 0; | |
176 | ||
177 | while (*table) | |
178 | { | |
179 | if (*table == '\\') | |
180 | { | |
181 | table += 2; | |
182 | ret += 1 + (compress ? 0 : 1); | |
183 | } | |
184 | else | |
185 | { | |
186 | if (*table == '\"') return ret; | |
187 | ret++; | |
188 | table++; | |
189 | } | |
190 | } | |
191 | return ret; | |
192 | } | |
193 | ||
194 | // looks in table for strings of format << "key" = "value"; >> | |
195 | // or << "key"; >> | |
196 | BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size) | |
197 | { | |
198 | int keyLength; | |
199 | char *tableKey; | |
200 | ||
201 | do | |
202 | { | |
203 | eatThru('\"',&table); | |
204 | tableKey = table; | |
205 | keyLength = strlen(key); | |
206 | if (keyLength && | |
207 | (stringLength(table,1) == keyLength) && | |
208 | (keyncmp(key, table, keyLength) == 0)) | |
209 | { | |
210 | int c; | |
211 | ||
212 | /* found the key; now look for either | |
213 | * '=' or ';' | |
214 | */ | |
215 | while (c = *table) { | |
216 | ++table; | |
217 | if (c == '\\') { | |
218 | ++table; | |
219 | continue; | |
220 | } else if (c == '=' || c == ';') { | |
221 | break; | |
222 | } | |
223 | } | |
224 | if (c == ';') { | |
225 | table = tableKey; | |
226 | } else { | |
227 | eatThru('\"',&table); | |
228 | } | |
229 | *val = table; | |
230 | *size = stringLength(table,0); | |
231 | return YES; | |
232 | } | |
233 | ||
234 | eatThru(';',&table); | |
235 | ||
236 | } while (*table); | |
237 | ||
238 | return NO; | |
239 | } | |
240 | ||
241 | ||
242 | /* | |
243 | * Returns a new malloc'ed string if one is found | |
244 | * in the string table matching 'key'. Also translates | |
245 | * \n escapes in the string. | |
246 | */ | |
247 | char *newStringForStringTableKey( | |
248 | char *table, | |
249 | char *key | |
250 | ) | |
251 | { | |
252 | char *val, *newstr, *p; | |
253 | int size; | |
254 | ||
255 | if (getValueForStringTableKey(table, key, &val, &size)) { | |
256 | newstr = malloc(size+1); | |
257 | for (p = newstr; size; size--, p++, val++) { | |
258 | if ((*p = *val) == '\\') { | |
259 | switch (*++val) { | |
260 | case 'r': | |
261 | *p = '\r'; | |
262 | break; | |
263 | case 'n': | |
264 | *p = '\n'; | |
265 | break; | |
266 | case 't': | |
267 | *p = '\t'; | |
268 | break; | |
269 | default: | |
270 | *p = *val; | |
271 | break; | |
272 | } | |
273 | size--; | |
274 | } | |
275 | } | |
276 | *p = '\0'; | |
277 | return newstr; | |
278 | } else { | |
279 | return 0; | |
280 | } | |
281 | } | |
282 | ||
283 | char * | |
284 | newStringForKey(char *key) | |
285 | { | |
286 | char *val, *newstr; | |
287 | int size; | |
288 | ||
289 | if (getValueForKey(key, &val, &size) && size) { | |
290 | newstr = malloc(size + 1); | |
291 | strncpy(newstr, val, size); | |
292 | return newstr; | |
293 | } else { | |
294 | return 0; | |
295 | } | |
296 | } | |
297 | ||
298 | /* parse a command line | |
299 | * in the form: [<argument> ...] [<option>=<value> ...] | |
300 | * both <option> and <value> must be either composed of | |
301 | * non-whitespace characters, or enclosed in quotes. | |
302 | */ | |
303 | ||
304 | static char *getToken(char *line, char **begin, int *len) | |
305 | { | |
306 | if (*line == '\"') { | |
307 | *begin = ++line; | |
308 | while (*line && *line != '\"') | |
309 | line++; | |
310 | *len = line++ - *begin; | |
311 | } else { | |
312 | *begin = line; | |
313 | while (*line && !isspace(*line) && *line != '=') | |
314 | line++; | |
315 | *len = line - *begin; | |
316 | } | |
317 | return line; | |
318 | } | |
319 | ||
320 | BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len) | |
321 | { | |
322 | char *key, *value; | |
323 | int key_len, value_len; | |
324 | ||
325 | while (*line) { | |
326 | /* look for keyword or argument */ | |
327 | while (isspace(*line)) line++; | |
328 | ||
329 | /* now look for '=' or whitespace */ | |
330 | line = getToken(line, &key, &key_len); | |
331 | /* line now points to '=' or space */ | |
332 | if (*line && !isspace(*line)) { | |
333 | line = getToken(++line, &value, &value_len); | |
334 | } else { | |
335 | value = line; | |
336 | value_len = 0; | |
337 | } | |
338 | if ((strlen(match) == key_len) | |
339 | && strncmp(match, key, key_len) == 0) { | |
340 | *matchval = value; | |
341 | *len = value_len; | |
342 | return YES; | |
343 | } | |
344 | } | |
345 | return NO; | |
346 | } | |
347 | ||
348 | BOOL getBoolForKey( | |
349 | char *key | |
350 | ) | |
351 | { | |
352 | char *val; | |
353 | int size; | |
354 | ||
355 | if (getValueForKey(key, &val, &size) && (size >= 1) && | |
356 | val[0] == 'Y' || val[0] == 'y') | |
357 | return YES; | |
358 | return NO; | |
359 | } | |
360 | ||
361 | BOOL getIntForKey( | |
362 | char *key, | |
363 | int *value | |
364 | ) | |
365 | { | |
366 | char *val; | |
367 | int size, sum; | |
368 | ||
369 | if (getValueForKey(key, &val, &size)) { | |
370 | for (sum = 0; size > 0; size--) { | |
371 | sum = (sum * 10) + (*val++ - '0'); | |
372 | } | |
373 | *value = sum; | |
374 | return YES; | |
375 | } | |
376 | return NO; | |
377 | } | |
378 | ||
379 | BOOL getValueForKey( | |
380 | char *key, | |
381 | char **val, | |
382 | int *size | |
383 | ) | |
384 | { | |
385 | if (getValueForBootKey(kernBootStruct->bootString, key, val, size)) | |
386 | return YES; | |
387 | else if (getValueForStringTableKey(kernBootStruct->config, key, val, size)) | |
388 | return YES; | |
389 | ||
390 | return NO; | |
391 | } | |
392 | ||
393 | #if 0 | |
394 | #define LOCALIZABLE_PATH \ | |
395 | "%s/%s.config/%s.lproj/%s.strings" | |
396 | char * | |
397 | loadLocalizableStrings( | |
398 | char *name, | |
399 | char *tableName | |
400 | ) | |
401 | { | |
402 | char buf[256], *config; | |
403 | register int count, fd = -1; | |
404 | char *device_dir = usrDevices(); | |
405 | ||
406 | sprintf(buf, LOCALIZABLE_PATH, device_dir, name, | |
407 | Language, tableName); | |
408 | if ((fd = open(buf, 0)) < 0) { | |
409 | sprintf(buf, LOCALIZABLE_PATH, device_dir, name, | |
410 | "English", tableName); | |
411 | if ((fd = open(buf,0)) < 0) { | |
412 | return 0; | |
413 | } | |
414 | } | |
415 | count = file_size(fd); | |
416 | config = malloc(count); | |
417 | count = read(fd, config, count); | |
418 | close(fd); | |
419 | if (count <= 0) { | |
420 | free(config); | |
421 | return 0; | |
422 | } | |
423 | return config; | |
424 | } | |
425 | #endif | |
426 | ||
427 | #if 0 // XXX | |
428 | char * | |
429 | bundleLongName( | |
430 | char *bundleName, | |
431 | char *tableName | |
432 | ) | |
433 | { | |
434 | char *table, *name, *version, *newName; | |
435 | char *path = malloc(256); | |
436 | ||
437 | #define LONG_NAME_FORMAT "%s (v%s)" | |
438 | sprintf(path, "%s/%s.config/%s.table", | |
439 | usrDevices(), bundleName, tableName ? tableName : "Default"); | |
440 | if (loadConfigFile(path, &table, YES) == 0) { | |
441 | version = newStringForStringTableKey(table, "Version"); | |
442 | free(table); | |
443 | } else { | |
444 | version = newString("0.0"); | |
445 | } | |
446 | table = loadLocalizableStrings(bundleName, | |
447 | tableName ? tableName : "Localizable"); | |
448 | if (table) { | |
449 | name = newStringForStringTableKey(table, "Long Name"); | |
450 | free(table); | |
451 | } else { | |
452 | name = newString(bundleName); | |
453 | } | |
454 | newName = malloc(strlen(name)+strlen(version)+strlen(LONG_NAME_FORMAT)); | |
455 | sprintf(newName, LONG_NAME_FORMAT, name, version); | |
456 | free(name); free(version); | |
457 | return newName; | |
458 | } | |
459 | #endif | |
460 | ||
461 | int sysConfigValid; | |
462 | ||
463 | void | |
464 | addConfig( | |
465 | char *config | |
466 | ) | |
467 | { | |
468 | char *configPtr = kernBootStruct->configEnd; | |
469 | int len = strlen(config); | |
470 | ||
471 | if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) { | |
472 | error("No room in memory for config files\n"); | |
473 | return; | |
474 | } | |
475 | strcpy(configPtr, config); | |
476 | configPtr += (len + 1); | |
477 | *configPtr = 0; | |
478 | kernBootStruct->configEnd = configPtr; | |
479 | } | |
480 | ||
481 | #define TABLE_EXPAND_SIZE 192 | |
482 | ||
483 | /* | |
484 | * Returns 0 if file loaded OK, | |
485 | * -1 if file was not loaded | |
486 | * Does not print error messages. | |
487 | * Returns pointer to table in memory in *table. | |
488 | * Allocates an extra number of bytes for table expansion. | |
489 | */ | |
490 | int | |
491 | loadConfigFile( char *configFile, char **table, BOOL allocTable) | |
492 | { | |
493 | char *configPtr = kernBootStruct->configEnd; | |
494 | int fd, count; | |
495 | ||
496 | /* Read config file into memory */ | |
497 | if ((fd = open(configFile, 0)) >= 0) | |
498 | { | |
499 | if (allocTable) { | |
500 | configPtr = malloc(file_size(fd)+2+TABLE_EXPAND_SIZE); | |
501 | } else { | |
502 | if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) { | |
503 | error("No room in memory for config files\n"); | |
504 | close(fd); | |
505 | return -1; | |
506 | } | |
507 | verbose("Reading configuration file '%s'.\n",configFile); | |
508 | } | |
509 | if (table) *table = configPtr; | |
510 | count = read(fd, configPtr, IO_CONFIG_DATA_SIZE); | |
511 | close(fd); | |
512 | ||
513 | configPtr += count; | |
514 | *configPtr++ = 0; | |
515 | *configPtr = 0; | |
516 | if (!allocTable) | |
517 | kernBootStruct->configEnd = configPtr; | |
518 | ||
519 | return 0; | |
520 | } else { | |
521 | return -1; | |
522 | } | |
523 | } | |
524 | ||
525 | /* Returns 0 if requested config files were loaded, | |
526 | * 1 if default files were loaded, | |
527 | * -1 if no files were loaded. | |
528 | * Prints error message if files cannot be loaded. | |
529 | */ | |
530 | ||
531 | int | |
532 | loadConfigDir( | |
533 | char *bundleName, // bundle directory name (e.g. "System") | |
534 | BOOL useDefault, // use Default.table instead of instance tables | |
535 | char **table, // returns pointer to config table | |
536 | BOOL allocTable // malloc the table and return in *table | |
537 | ) | |
538 | { | |
539 | char *buf; | |
540 | int i, max, ret; | |
541 | char *device_dir = usrDevices(); | |
542 | ||
543 | buf = malloc(256); | |
544 | ret = 0; | |
545 | ||
546 | // load up to 99 instance tables | |
547 | if (allocTable) | |
548 | max = 1; | |
549 | else | |
550 | max = 99; | |
551 | for (i=0; i < max; i++) { | |
552 | sprintf(buf, "%s/%s.config/Instance%d.table", | |
553 | device_dir, | |
554 | bundleName, i); | |
555 | if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) { | |
556 | if (i == 0) { | |
557 | // couldn't load first instance table; | |
558 | // try the default table | |
559 | sprintf(buf, "%s/%s.config/%s", | |
560 | device_dir, | |
561 | bundleName, | |
562 | IO_DEFAULT_TABLE_FILENAME); | |
563 | if (loadConfigFile(buf, table, allocTable) == 0) { | |
564 | ret = 1; | |
565 | } else { | |
566 | if (!allocTable) | |
567 | error("Config file \"%s\" not found\n", buf); | |
568 | ret = -1; | |
569 | } | |
570 | } | |
571 | // we must be done. | |
572 | break; | |
573 | } | |
574 | } | |
575 | free(buf); | |
576 | return ret; | |
577 | } | |
578 | ||
579 | ||
580 | #define USR_SYSTEM_CONFIG \ | |
581 | USR_DEVICES "/System.config" | |
582 | #define USR_SYSTEM_DEFAULT_FILE \ | |
583 | USR_SYSTEM_CONFIG "/Default.table" | |
584 | #define ARCH_SYSTEM_CONFIG \ | |
585 | ARCH_DEVICES "/System.config" | |
586 | #define ARCH_SYSTEM_DEFAULT_FILE \ | |
587 | ARCH_SYSTEM_CONFIG "/Default.table" | |
588 | #define SYSTEM_CONFIG "System" | |
589 | #define LP '(' | |
590 | #define RP ')' | |
591 | ||
592 | static int sysconfig_dev; | |
593 | ||
594 | /* Returns 0 if requested config files were loaded, | |
595 | * 1 if default files were loaded, | |
596 | * -1 if no files were loaded. | |
597 | * Prints error message if files cannot be loaded. | |
598 | */ | |
599 | int | |
600 | loadSystemConfig( | |
601 | char *which, | |
602 | int size | |
603 | ) | |
604 | { | |
605 | char *buf, *bp, *cp; | |
606 | int ret, len, doDefault=0; | |
607 | char *device_dir = usrDevices(); | |
608 | ||
609 | #if 0 | |
610 | printf("In Load system config which=%d ; size=%d\n", which, size); | |
611 | //sleep(1); | |
612 | #endif 1 | |
613 | buf = bp = malloc(256); | |
614 | if (which && size) | |
615 | { | |
616 | #if 0 | |
617 | printf("In Load system config alt\n"); | |
618 | //sleep(1); | |
619 | #endif 1 | |
620 | for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ; | |
621 | if (*cp == LP) { | |
622 | while (len-- && *cp && *cp++ != RP) ; | |
623 | /* cp now points past device */ | |
624 | strncpy(buf,which,cp - which); | |
625 | bp += cp - which; | |
626 | } else { | |
627 | cp = which; | |
628 | len = size; | |
629 | } | |
630 | if (*cp != '/') { | |
631 | strcpy(bp, device_dir); | |
632 | strcat(bp, "/System.config/"); | |
633 | strncat(bp, cp, len); | |
634 | if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION), | |
635 | IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0) | |
636 | strcat(bp, IO_TABLE_EXTENSION); | |
637 | } else { | |
638 | strncpy(bp, cp, len); | |
639 | bp[size] = '\0'; | |
640 | } | |
641 | if ((strcmp(bp, USR_SYSTEM_DEFAULT_FILE) == 0) || | |
642 | (strcmp(bp, ARCH_SYSTEM_DEFAULT_FILE) == 0)) | |
643 | doDefault = 1; | |
644 | ret = loadConfigFile(bp = buf, 0, 0); | |
645 | } else { | |
646 | #if 0 | |
647 | printf("In default SYSTEM_CONFIG LOAD\n"); | |
648 | //sleep(1); | |
649 | #endif 1 | |
650 | ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0); | |
651 | #if 0 | |
652 | printf("come back from SYSTEM_CONFIG loadConfigDir\n"); | |
653 | //sleep(1); | |
654 | #endif 1 | |
655 | } | |
656 | sysconfig_dev = currentdev(); | |
657 | if (ret < 0) { | |
658 | error("System config file '%s' not found\n", bp); | |
659 | } else | |
660 | sysConfigValid = 1; | |
661 | free(buf); | |
662 | return (ret < 0 ? ret : doDefault); | |
663 | } | |
664 | ||
665 | #ifdef DISABLED | |
666 | int | |
667 | loadOtherConfigs( | |
668 | int useDefault | |
669 | ) | |
670 | { | |
671 | char *val, *table; | |
672 | char *path = malloc(256); | |
673 | char *hintTable; | |
674 | char *installVersion = NULL, *thisVersion; | |
675 | char *longName, *tableName; | |
676 | int count; | |
677 | char *string; | |
678 | int ret; | |
679 | int old_dev = currentdev(); | |
680 | ||
681 | if (sysconfig_dev) | |
682 | switchdev(sysconfig_dev); | |
683 | if (getValueForKey( "Boot Drivers", &val, &count)) | |
684 | { | |
685 | #if 0 | |
686 | printf("Loading Boot Drivers\n"); | |
687 | sleep(1); | |
688 | #endif 1 | |
689 | while (string = newStringFromList(&val, &count)) { | |
690 | /* Check installation hints... */ | |
691 | sprintf(path, "%s/System.config/" INSTALL_HINTS | |
692 | "/%s.table", usrDevices(), string); | |
693 | ||
694 | if (getBoolForKey("Ignore Hints") == NO && | |
695 | loadConfigFile(path, &hintTable, YES) == 0) { | |
696 | installVersion = newStringForStringTableKey( | |
697 | hintTable, "Version"); | |
698 | longName = newStringForStringTableKey( | |
699 | hintTable, "Long Name"); | |
700 | tableName = newStringForStringTableKey( | |
701 | hintTable, "Default Table"); | |
702 | free(hintTable); | |
703 | } else { | |
704 | installVersion = longName = tableName = NULL; | |
705 | } | |
706 | ||
707 | ret = loadConfigDir(string, useDefault, &table, YES); | |
708 | if (ret >= 0) { | |
709 | thisVersion = newStringForStringTableKey( | |
710 | table, "Version"); | |
711 | if (installVersion && thisVersion && | |
712 | (strcmp(thisVersion, installVersion) != 0)) { | |
713 | /* Versions do not match */ | |
714 | driverIsMissing(string, installVersion, longName, | |
715 | tableName, DRIVER_VERSION_MISMATCH); | |
716 | } else { | |
717 | struct driver_load_data dl; | |
718 | ||
719 | dl.name = string; | |
720 | if ((openDriverReloc(&dl)) >= 0) { | |
721 | verbose("Loading binary for %s device driver.\n",string); | |
722 | if (loadDriver(&dl) < 0) /// need to stop if error | |
723 | error("Error loading %s device driver.\n",string); | |
724 | #if 0 | |
725 | printf("Calling link driver for %s\n", string); | |
726 | #endif 1 | |
727 | if (linkDriver(&dl) < 0) | |
728 | error("Error linking %s device Driver.\n",string); | |
729 | } | |
730 | loadConfigDir(string, useDefault, NULL, NO); | |
731 | driverWasLoaded(string, table, NULL); | |
732 | free(table); | |
733 | free(string); | |
734 | free(installVersion); free(longName); | |
735 | free(tableName); | |
736 | } | |
737 | free(thisVersion); | |
738 | } else { | |
739 | /* driver not found */ | |
740 | driverIsMissing(string, installVersion, longName, | |
741 | tableName, DRIVER_NOT_FOUND); | |
742 | } | |
743 | #if 0 | |
744 | if (ret == 1) | |
745 | useDefault = 1; // use defaults from now on | |
746 | #endif | |
747 | } | |
748 | } else { | |
749 | error("Warning: No Boot drivers specified in system config.\n"); | |
750 | } | |
751 | ||
752 | kernBootStruct->first_addr0 = | |
753 | (int)kernBootStruct->configEnd + 1024; | |
754 | free(path); | |
755 | switchdev(old_dev); | |
756 | return 0; | |
757 | } | |
758 | #endif /* DISABLED */ |