kernel/sys/config.c

137 lines
3.6 KiB
C
Raw Normal View History

#include "sys/config.h"
#include "sys/string.h"
#include "sys/ctype.h"
#include "sys/debug.h"
#define VALUE_BOOLEAN 0
#define VALUE_NUMBER 1
#define VALUE_STRING 2
// Cmdline parameter list
static const struct __kernel_cmdline_pair {
const char *key;
int cfg_index;
int value_type;
} kernel_cmdline_pairs[] = {
{ "root", CFG_ROOT, VALUE_STRING },
{ "init", CFG_INIT, VALUE_STRING },
2020-01-22 15:01:37 +02:00
{ "console", CFG_CONSOLE, VALUE_STRING },
2020-01-22 15:31:57 +02:00
{ "debug", CFG_DEBUG, VALUE_NUMBER },
};
2020-01-26 00:32:23 +02:00
char g_kernel_cmdline[KERNEL_CMDLINE_MAX];
// Default config
uintptr_t kernel_config[__CFG_SIZE] = {
0,
[CFG_ROOT] = (uintptr_t) "ram0",
[CFG_INIT] = (uintptr_t) "/init",
2020-01-22 15:01:37 +02:00
[CFG_CONSOLE] = (uintptr_t) "tty0",
2020-01-22 15:31:57 +02:00
[CFG_DEBUG] = DEBUG_ALL_SERIAL |
2020-09-18 14:23:20 +03:00
DEBUG_DISP(DEBUG_INFO) |
DEBUG_DISP(DEBUG_WARN) |
DEBUG_DISP(DEBUG_ERROR) |
DEBUG_DISP(DEBUG_FATAL),
};
static int parse_number(const char *s, intptr_t *res) {
*res = 0;
while (isdigit(*s)) {
*res *= 10;
*res += (*s) - '0';
2020-01-22 15:31:57 +02:00
++s;
}
if (*s) {
// Not a digit
return -1;
}
return 0;
}
static void kernel_set_opt(const struct __kernel_cmdline_pair *pair, const char *key, const char *value) {
uintptr_t new_value;
if ((pair->value_type != VALUE_BOOLEAN) && !value) {
kwarn("Cmdline option requires a value: \"%s\"\n", key);
return;
}
switch (pair->value_type) {
case VALUE_BOOLEAN:
if (value) {
// Check if it's "false", "no", "off" or "true", "yes", "on"
if (!strcmp(value, "false") || !strcmp(value, "no") || !strcmp(value, "off")) {
new_value = 0;
} else if (!strcmp(value, "true") || !strcmp(value, "yes") || !strcmp(value, "on")) {
new_value = 1;
} else {
kwarn("Cmdline flag has invalid value: \"%s=%s\", expected boolean\n", key, value);
return;
}
} else {
// Just "opt" without value - assume it's true
new_value = 1;
}
break;
case VALUE_STRING:
// TODO: use a separate array for strings
new_value = (uintptr_t) value;
kdebug("opt \"%s=%s\" (string)\n", key, value);
break;
case VALUE_NUMBER:
if (parse_number(value, (intptr_t *) &new_value) != 0) {
kerror("Cmdline option is not a number: \"%s=%s\"\n", key, value);
return;
}
break;
default:
kerror("Invalid value type, kernel is fucked up\n");
return;
}
kernel_config[pair->cfg_index] = new_value;
}
static void kernel_cmdline_opt(char *opt) {
char *key = opt;
char *value = NULL;
if ((value = strchr(opt, '='))) {
*value = 0;
++value;
}
for (size_t i = 0; i < sizeof(kernel_cmdline_pairs) / sizeof(kernel_cmdline_pairs[0]); ++i) {
if (!strcmp(kernel_cmdline_pairs[i].key, key)) {
kernel_set_opt(&kernel_cmdline_pairs[i], key, value);
return;
}
}
kwarn("Unknown cmdline option: \"%s\"\n", key);
}
// TODO: support stuff with spaces
void kernel_set_cmdline(char *cmdline) {
2020-01-26 00:32:23 +02:00
strcpy(g_kernel_cmdline, cmdline);
char *p = cmdline;
while (1) {
while (isspace(*p)) {
++p;
}
char *e = strchr(p, ' ');
if (e) {
*e = 0;
}
kernel_cmdline_opt(p);
if (!e) {
break;
}
p = e + 1;
}
}