CloverBootloader/Trash/stringTable.c

570 lines
11 KiB
C

/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.1 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright 1993 NeXT, Inc.
* All rights reserved.
*/
//#import "libsaio.h"
//#import "bootstruct.h"
//#import <driverkit/configTablePrivate.h>
extern char *Language;
extern char *LoadableFamilies;
static void eatThru(char val, char **table_p);
static __inline INTN isspace(char c)
{
return (c == ' ' || c == '\t');
}
/*
* Compare a string to a key with quoted characters
*/
static __inline int
keyncmp(char *str, char *key, INTN n)
{
INTN c;
while (n--) {
c = *key++;
if (c == '\\') {
switch(c = *key++) {
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
default:
break;
}
} else if (c == '\"') {
/* Premature end of key */
return 1;
}
if (c != *str++) {
return 1;
}
}
return 0;
}
static void eatThru(char val, char **table_p)
{
register char *table = *table_p;
register BOOL found = NO;
while (*table && !found)
{
if (*table == '\\') table += 2;
else
{
if (*table == val) found = YES;
table++;
}
}
*table_p = table;
}
char *
newStringFromList(
char **list,
INTN* size
)
{
char *begin = *list, *end;
char *newstr;
INTN newsize = *size;
while (*begin && newsize && isspace(*begin)) {
begin++;
newsize--;
}
end = begin;
while (*end && newsize && !isspace(*end)) {
end++;
newsize--;
}
if (begin == end)
return 0;
newstr = malloc(end - begin + 1);
strncpy(newstr, begin, end - begin);
*list = end;
*size = newsize;
return newstr;
}
/*
* compress == compress escaped characters to one character
*/
int stringLength(char *table, INTN compress)
{
int ret = 0;
while (*table)
{
if (*table == '\\')
{
table += 2;
ret += 1 + (compress ? 0 : 1);
}
else
{
if (*table == '\"') return ret;
ret++;
table++;
}
}
return ret;
}
// looks in table for strings of format << "key" = "value"; >>
// or << "key"; >>
BOOL getValueForStringTableKey(char *table, char *key, char **val, INTN *size)
{
INTN keyLength;
char *tableKey;
do
{
eatThru('\"',&table);
tableKey = table;
keyLength = strlen(key);
if (keyLength &&
(stringLength(table,1) == keyLength) &&
(keyncmp(key, table, keyLength) == 0))
{
INTN c;
/* found the key; now look for either
* '=' or ';'
*/
while (c = *table) {
++table;
if (c == '\\') {
++table;
continue;
} else if (c == '=' || c == ';') {
break;
}
}
if (c == ';') {
table = tableKey;
} else {
eatThru('\"',&table);
}
*val = table;
*size = stringLength(table,0);
return YES;
}
eatThru(';',&table);
} while (*table);
return NO;
}
/*
* Returns a new malloc'ed string if one is found
* in the string table matching 'key'. Also translates
* \n escapes in the string.
*/
char *newStringForStringTableKey(
char *table,
char *key
)
{
char *val, *newstr, *p;
INTN size;
if (getValueForStringTableKey(table, key, &val, &size)) {
newstr = malloc(size+1);
for (p = newstr; size; size--, p++, val++) {
if ((*p = *val) == '\\') {
switch (*++val) {
case 'r':
*p = '\r';
break;
case 'n':
*p = '\n';
break;
case 't':
*p = '\t';
break;
default:
*p = *val;
break;
}
size--;
}
}
*p = '\0';
return newstr;
} else {
return 0;
}
}
char *
newStringForKey(char *key)
{
char *val, *newstr;
INTN size;
if (getValueForKey(key, &val, &size) && size) {
newstr = malloc(size + 1);
strncpy(newstr, val, size);
return newstr;
} else {
return 0;
}
}
/* parse a command line
* in the form: [<argument> ...] [<option>=<value> ...]
* both <option> and <value> must be either composed of
* non-whitespace characters, or enclosed in quotes.
*/
static char *getToken(char *line, char **begin, INTN *len)
{
if (*line == '\"') {
*begin = ++line;
while (*line && *line != '\"')
line++;
*len = line++ - *begin;
} else {
*begin = line;
while (*line && !isspace(*line) && *line != '=')
line++;
*len = line - *begin;
}
return line;
}
BOOL getValueForBootKey(char *line, char *match, char **matchval, INTN *len)
{
char *key, *value;
INTN key_len, value_len;
while (*line) {
/* look for keyword or argument */
while (isspace(*line)) line++;
/* now look for '=' or whitespace */
line = getToken(line, &key, &key_len);
/* line now points to '=' or space */
if (!isspace(*line++)) {
line = getToken(line, &value, &value_len);
if ((strlen(match) == key_len)
&& strncmp(match, key, key_len) == 0) {
*matchval = value;
*len = value_len;
return YES;
}
}
}
return NO;
}
BOOL getBoolForKey(
char *key
)
{
char *val;
INTN, size;
if (getValueForKey(key, &val, &size) && (size >= 1) &&
val[0] == 'Y' || val[0] == 'y')
return YES;
return NO;
}
BOOL getValueForKey(
char *key,
char **val,
INTN *size
)
{
if (getValueForBootKey(bootArgs->bootString, key, val, size))
return YES;
else if (getValueForStringTableKey(bootArgs->config, key, val, size))
return YES;
return NO;
}
#define LOCALIZABLE \
"/usr/Devices/%s.config/%s.lproj/Localizable.strings"
char *
loadLocalizableStrings(
char *name
)
{
char buf[256], *config;
register INTN count, fd;
sprintf(buf, LOCALIZABLE, name, Language);
if ((fd = open(buf,0)) < 0) {
sprintf(buf, LOCALIZABLE, name, "English");
if ((fd = open(buf,0)) < 0)
return 0;
}
count = file_size(fd);
config = malloc(count);
count = read(fd, config, count);
close(fd);
if (count <= 0) {
free(config);
return 0;
}
return config;
}
char *
bundleLongName(
char *bundleName
)
{
char *table, *name, *val;
INTN, size;
if ((table = loadLocalizableStrings(bundleName)) != 0 &&
getValueForStringTableKey(table,"Long Name", &val, &size) == YES) {
name = malloc(size+1);
strncpy(name, val, size);
free(table);
} else {
name = newString(bundleName);
}
return name;
}
int sysConfigValid;
/*
* Returns 0 if file loaded OK,
* -1 if file was not loaded
* Does not print error messages.
* Returns pointer to table in memory in *table.
*/
int
loadConfigFile( char *configFile, char **table, INTN allocTable)
{
char *configPtr = bootArgs->configEnd;
INTN fd, count;
/* Read config file into memory */
if ((fd = open(configFile, 0)) >= 0)
{
if (allocTable) {
configPtr = malloc(file_size(fd)+2);
} else {
if ((configPtr - bootArgs->config) > CONFIG_SIZE) {
error("No room in memory for config file %s\n",configFile);
close(fd);
return -1;
}
localPrintf("Reading config: %s\n",configFile);
}
if (table) *table = configPtr;
count = read(fd, configPtr, IO_CONFIG_DATA_SIZE);
close(fd);
configPtr += count;
*configPtr++ = 0;
*configPtr = 0;
if (!allocTable)
bootArgs->configEnd = configPtr;
return 0;
} else {
return -1;
}
}
/* Returns 0 if requested config files were loaded,
* 1 if default files were loaded,
* -1 if no files were loaded.
* Prints error message if files cannot be loaded.
*/
int
loadConfigDir(
char *bundleName, // bundle directory name (e.g. "System.config")
INTN useDefault, // use Default.table instead of instance tables
char **table, // returns pointer to config table
INTN allocTable // malloc the table and return in *table
)
{
char *buf;
INTN i, ret;
buf = malloc(256);
ret = 0;
// load up to 99 instance tables
for (i=0; i < 99; i++) {
sprintf(buf, "%s%s.config/Instance%d.table", IO_CONFIG_DIR,
bundleName, i);
if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) {
if (i == 0) {
// couldn't load first instance table;
// try the default table
sprintf(buf, "%s%s.config/%s", IO_CONFIG_DIR, bundleName,
IO_DEFAULT_TABLE_FILENAME);
if (loadConfigFile(buf, table, allocTable) == 0) {
ret = 1;
} else {
if (!allocTable)
error("Config file \"%s\" not found\n", buf);
ret = -1;
}
}
// we must be done.
break;
}
}
free(buf);
return ret;
}
#define SYSTEM_DEFAULT_FILE \
IO_SYSTEM_CONFIG_DIR IO_DEFAULT_TABLE_FILENAME
#define SYSTEM_CONFIG "System"
#define LP '('
#define RP ')'
/* Returns 0 if requested config files were loaded,
* 1 if default files were loaded,
* -1 if no files were loaded.
* Prints error message if files cannot be loaded.
*/
int
loadSystemConfig(
char *which,
INTN size
)
{
char *buf, *bp, *cp;
INTN ret, len, doDefault=0;
buf = bp = malloc(256);
if (which && size)
{
for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
if (*cp == LP) {
while (len-- && *cp && *cp++ != RP) ;
/* cp now points past device */
strncpy(buf,which,cp - which);
bp += cp - which;
} else {
cp = which;
len = size;
}
if (*cp != '/') {
strcpy(bp, IO_SYSTEM_CONFIG_DIR);
strncat(bp, cp, len);
if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION),
IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0)
strcat(bp, IO_TABLE_EXTENSION);
} else {
strncpy(bp, cp, len);
bp[size] = '\0';
}
if (strcmp(bp, SYSTEM_DEFAULT_FILE) == 0)
doDefault = 1;
ret = loadConfigFile(bp = buf, 0, 0);
} else {
ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0);
}
if (ret < 0) {
error("System config file '%s' not found\n", bp);
} else
sysConfigValid = 1;
free(buf);
return (ret < 0 ? ret : doDefault);
}
int
loadOtherConfigs(
INTN useDefault
)
{
char *val, *table;
INTN count;
char *string;
INTN fd, ret;
if (getValueForKey( "Boot Drivers", &val, &count))
{
while (string = newStringFromList(&val, &count)) {
ret = loadConfigDir(string, useDefault, &table, 0);
if (ret >= 0) {
if ((fd = openDriverReloc(string)) >= 0) {
localPrintf("Loading binary for %s\n",string);
if (loadDriver(string, fd) < 0)
error("Error loading driver %s\n",string);
close(fd);
}
driverWasLoaded(string, table);
free(string);
} else {
driverIsMissing(string);
}
if (ret == 1)
useDefault = 1; // use defaults from now on
}
} else {
error("Warning: No active drivers specified in system config\n");
}
bootArgs->first_addr0 =
(int)bootArgs->configEnd + 1024;
return 0;
}