2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
30 #include "stringConstants.h"
31 #include "legacy/configTablePrivate.h"
33 extern KERNBOOTSTRUCT
*kernBootStruct
;
34 extern char *Language
;
35 extern char *LoadableFamilies
;
37 static void eatThru(char val
, const char **table_p
);
39 static inline int isspace(char c
)
41 return (c
== ' ' || c
== '\t');
45 * Compare a string to a key with quoted characters
48 keyncmp(const char *str
, const char *key
, int n
)
67 } else if (c
== '\"') {
68 /* Premature end of key */
78 static void eatThru(char val
, const char **table_p
)
80 register const char *table
= *table_p
;
81 register BOOL found
= NO
;
83 while (*table
&& !found
)
85 if (*table
== '\\') table
+= 2;
88 if (*table
== val
) found
= YES
;
95 /* Remove key and its associated value from the table. */
98 removeKeyFromTable(const char *key
, char *table
)
106 buf
= (char *)malloc(len
+ 3);
108 sprintf(buf
, "\"%s\"", key
);
112 if(strncmp(buf
, tab
, len
) == 0) {
115 while((c
= *(tab
+ len
)) != ';') {
123 if(*(tab
+ len
) == '\n') len
++;
132 if(len
== -1) return NO
;
134 while((*tab
= *(tab
+ len
))) {
147 char *begin
= *list
, *end
;
151 while (*begin
&& newsize
&& isspace(*begin
)) {
156 while (*end
&& newsize
&& !isspace(*end
)) {
162 newstr
= malloc(end
- begin
+ 1);
163 strncpy(newstr
, begin
, end
- begin
);
170 * compress == compress escaped characters to one character
172 int stringLength(const char *table
, int compress
)
181 ret
+= 1 + (compress
? 0 : 1);
185 if (*table
== '\"') return ret
;
193 // looks in table for strings of format << "key" = "value"; >>
195 BOOL
getValueForStringTableKey(const char *table
, const char *key
, const char **val
, int *size
)
198 const char *tableKey
;
202 eatThru('\"',&table
);
204 keyLength
= strlen(key
);
206 (stringLength(table
,1) == keyLength
) &&
207 (keyncmp(key
, table
, keyLength
) == 0))
211 /* found the key; now look for either
219 } else if (c
== '=' || c
== ';') {
226 eatThru('\"',&table
);
229 *size
= stringLength(table
,0);
242 * Returns a new malloc'ed string if one is found
243 * in the string table matching 'key'. Also translates
244 * \n escapes in the string.
246 char *newStringForStringTableKey(
255 if (getValueForStringTableKey(table
, key
, &val
, &size
)) {
256 newstr
= (char *)malloc(size
+1);
257 for (p
= newstr
; size
; size
--, p
++, val
++) {
258 if ((*p
= *val
) == '\\') {
284 newStringForKey(char *key
)
290 if (getValueForKey(key
, &val
, &size
) && size
) {
291 newstr
= (char *)malloc(size
+ 1);
292 strncpy(newstr
, val
, size
);
299 /* parse a command line
300 * in the form: [<argument> ...] [<option>=<value> ...]
301 * both <option> and <value> must be either composed of
302 * non-whitespace characters, or enclosed in quotes.
305 static const char *getToken(const char *line
, const char **begin
, int *len
)
309 while (*line
&& *line
!= '\"')
311 *len
= line
++ - *begin
;
314 while (*line
&& !isspace(*line
) && *line
!= '=')
316 *len
= line
- *begin
;
321 BOOL
getValueForBootKey(const char *line
, const char *match
, const char **matchval
, int *len
)
323 const char *key
, *value
;
324 int key_len
, value_len
;
327 /* look for keyword or argument */
328 while (isspace(*line
)) line
++;
330 /* now look for '=' or whitespace */
331 line
= getToken(line
, &key
, &key_len
);
332 /* line now points to '=' or space */
333 if (*line
&& !isspace(*line
)) {
334 line
= getToken(++line
, &value
, &value_len
);
339 if ((strlen(match
) == key_len
)
340 && strncmp(match
, key
, key_len
) == 0) {
356 if (getValueForKey(key
, &val
, &size
) && (size
>= 1) &&
357 val
[0] == 'Y' || val
[0] == 'y')
370 if (getValueForKey(key
, &val
, &size
)) {
371 for (sum
= 0; size
> 0; size
--) {
372 sum
= (sum
* 10) + (*val
++ - '0');
386 if (getValueForBootKey(kernBootStruct
->bootString
, key
, val
, size
))
388 else if (getValueForStringTableKey(kernBootStruct
->config
, key
, val
, size
))
395 #define LOCALIZABLE_PATH \
396 "%s/%s.config/%s.lproj/%s.strings"
398 loadLocalizableStrings(
403 char buf
[256], *config
;
404 register int count
, fd
= -1;
405 const char *device_dir
= usrDevices();
407 sprintf(buf
, LOCALIZABLE_PATH
, device_dir
, name
,
408 Language
, tableName
);
409 if ((fd
= open(buf
, 0)) < 0) {
410 sprintf(buf
, LOCALIZABLE_PATH
, device_dir
, name
,
411 "English", tableName
);
412 if ((fd
= open(buf
,0)) < 0) {
416 count
= file_size(fd
);
417 config
= malloc(count
);
418 count
= read(fd
, config
, count
);
435 char *table
, *name
, *version
, *newName
;
436 char *path
= malloc(256);
438 #define LONG_NAME_FORMAT "%s (v%s)"
439 sprintf(path
, "%s/%s.config/%s.table",
440 usrDevices(), bundleName
, tableName
? tableName
: "Default");
441 if (loadConfigFile(path
, &table
, YES
) == 0) {
442 version
= newStringForStringTableKey(table
, "Version");
445 version
= newString("0.0");
447 table
= loadLocalizableStrings(bundleName
,
448 tableName
? tableName
: "Localizable");
450 name
= newStringForStringTableKey(table
, "Long Name");
453 name
= newString(bundleName
);
455 newName
= malloc(strlen(name
)+strlen(version
)+strlen(LONG_NAME_FORMAT
));
456 sprintf(newName
, LONG_NAME_FORMAT
, name
, version
);
457 free(name
); free(version
);
469 char *configPtr
= kernBootStruct
->configEnd
;
470 int len
= strlen(config
);
472 if ((configPtr
- kernBootStruct
->config
) > CONFIG_SIZE
) {
473 error("No room in memory for config files\n");
476 strcpy(configPtr
, config
);
477 configPtr
+= (len
+ 1);
479 kernBootStruct
->configEnd
= configPtr
;
482 #define TABLE_EXPAND_SIZE 192
485 * Returns 0 if file loaded OK,
486 * -1 if file was not loaded
487 * Does not print error messages.
488 * Returns pointer to table in memory in *table.
489 * Allocates an extra number of bytes for table expansion.
492 loadConfigFile(const char *configFile
, const char **table
, BOOL allocTable
)
494 char *configPtr
= kernBootStruct
->configEnd
;
497 /* Read config file into memory */
498 if ((fd
= open(configFile
, 0)) >= 0)
501 configPtr
= malloc(file_size(fd
)+2+TABLE_EXPAND_SIZE
);
503 if ((configPtr
- kernBootStruct
->config
) > CONFIG_SIZE
) {
504 error("No room in memory for config files\n");
508 verbose("Reading configuration file '%s'.\n",configFile
);
510 if (table
) *table
= configPtr
;
511 count
= read(fd
, configPtr
, IO_CONFIG_DATA_SIZE
);
518 kernBootStruct
->configEnd
= configPtr
;
526 /* Returns 0 if requested config files were loaded,
527 * 1 if default files were loaded,
528 * -1 if no files were loaded.
529 * Prints error message if files cannot be loaded.
534 const char *bundleName
, // bundle directory name (e.g. "System")
535 BOOL useDefault
, // use Default.table instead of instance tables
536 const char **table
, // returns pointer to config table
537 BOOL allocTable
// malloc the table and return in *table
542 const char *device_dir
= usrDevices();
547 // load up to 99 instance tables
552 for (i
=0; i
< max
; i
++) {
553 sprintf(buf
, "%s/%s.config/Instance%d.table",
556 if (useDefault
|| (loadConfigFile(buf
, table
, allocTable
) != 0)) {
558 // couldn't load first instance table;
559 // try the default table
560 sprintf(buf
, "%s/%s.config/%s",
563 IO_DEFAULT_TABLE_FILENAME
);
564 if (loadConfigFile(buf
, table
, allocTable
) == 0) {
568 error("Config file \"%s\" not found\n", buf
);
581 #define USR_SYSTEM_CONFIG \
582 USR_DEVICES "/System.config"
583 #define USR_SYSTEM_DEFAULT_FILE \
584 USR_SYSTEM_CONFIG "/Default.table"
585 #define ARCH_SYSTEM_CONFIG \
586 ARCH_DEVICES "/System.config"
587 #define ARCH_SYSTEM_DEFAULT_FILE \
588 ARCH_SYSTEM_CONFIG "/Default.table"
589 #define SYSTEM_CONFIG "System"
593 static int sysconfig_dev
;
595 /* Returns 0 if requested config files were loaded,
596 * 1 if default files were loaded,
597 * -1 if no files were loaded.
598 * Prints error message if files cannot be loaded.
608 int ret
, len
, doDefault
=0;
609 const char *device_dir
= usrDevices();
612 printf("In Load system config which=%d ; size=%d\n", which
, size
);
615 buf
= bp
= malloc(256);
619 printf("In Load system config alt\n");
622 for(cp
= which
, len
= size
; len
&& *cp
&& *cp
!= LP
; cp
++, len
--) ;
624 while (len
-- && *cp
&& *cp
++ != RP
) ;
625 /* cp now points past device */
626 strncpy(buf
,which
,cp
- which
);
633 strcpy(bp
, device_dir
);
634 strcat(bp
, "/System.config/");
635 strncat(bp
, cp
, len
);
636 if (strncmp(cp
+ len
- strlen(IO_TABLE_EXTENSION
),
637 IO_TABLE_EXTENSION
, strlen(IO_TABLE_EXTENSION
)) != 0)
638 strcat(bp
, IO_TABLE_EXTENSION
);
640 strncpy(bp
, cp
, len
);
643 if ((strcmp(bp
, USR_SYSTEM_DEFAULT_FILE
) == 0) ||
644 (strcmp(bp
, ARCH_SYSTEM_DEFAULT_FILE
) == 0))
646 ret
= loadConfigFile(bp
= buf
, 0, 0);
649 printf("In default SYSTEM_CONFIG LOAD\n");
652 ret
= loadConfigDir((bp
= SYSTEM_CONFIG
), 0, 0, 0);
654 printf("come back from SYSTEM_CONFIG loadConfigDir\n");
658 sysconfig_dev
= currentdev();
660 error("System config file '%s' not found\n", bp
);
664 return (ret
< 0 ? ret
: doDefault
);
674 char *path
= malloc(256);
676 char *installVersion
= NULL
, *thisVersion
;
677 char *longName
, *tableName
;
681 int old_dev
= currentdev();
684 switchdev(sysconfig_dev
);
685 if (getValueForKey( "Boot Drivers", &val
, &count
))
688 printf("Loading Boot Drivers\n");
691 while (string
= newStringFromList(&val
, &count
)) {
692 /* Check installation hints... */
693 sprintf(path
, "%s/System.config/" INSTALL_HINTS
694 "/%s.table", usrDevices(), string
);
696 if (getBoolForKey("Ignore Hints") == NO
&&
697 loadConfigFile(path
, &hintTable
, YES
) == 0) {
698 installVersion
= newStringForStringTableKey(
699 hintTable
, "Version");
700 longName
= newStringForStringTableKey(
701 hintTable
, "Long Name");
702 tableName
= newStringForStringTableKey(
703 hintTable
, "Default Table");
706 installVersion
= longName
= tableName
= NULL
;
709 ret
= loadConfigDir(string
, useDefault
, &table
, YES
);
711 thisVersion
= newStringForStringTableKey(
713 if (installVersion
&& thisVersion
&&
714 (strcmp(thisVersion
, installVersion
) != 0)) {
715 /* Versions do not match */
716 driverIsMissing(string
, installVersion
, longName
,
717 tableName
, DRIVER_VERSION_MISMATCH
);
719 struct driver_load_data dl
;
722 if ((openDriverReloc(&dl
)) >= 0) {
723 verbose("Loading binary for %s device driver.\n",string
);
724 if (loadDriver(&dl
) < 0) /// need to stop if error
725 error("Error loading %s device driver.\n",string
);
727 printf("Calling link driver for %s\n", string
);
729 if (linkDriver(&dl
) < 0)
730 error("Error linking %s device Driver.\n",string
);
732 loadConfigDir(string
, useDefault
, NULL
, NO
);
733 driverWasLoaded(string
, table
, NULL
);
736 free(installVersion
); free(longName
);
741 /* driver not found */
742 driverIsMissing(string
, installVersion
, longName
,
743 tableName
, DRIVER_NOT_FOUND
);
747 useDefault
= 1; // use defaults from now on
751 error("Warning: No Boot drivers specified in system config.\n");
754 kernBootStruct
->first_addr0
=
755 (int)kernBootStruct
->configEnd
+ 1024;
760 #endif /* DISABLED */