Add config file parsing
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 6e20c0b9..5d7635c0 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -5,6 +5,13 @@
#include <drivers/vga_textmode.h>
#include <lib/real.h>
+uint64_t strtoui(const char *s) {
+ uint64_t n = 0;
+ while (*s)
+ n = n * 10 + ((*(s++)) - '0');
+ return n;
+}
+
char getchar(void) {
struct rm_regs r = {0};
rm_int(0x16, &r, &r);
diff --git a/src/lib/blib.h b/src/lib/blib.h
index 0cba0693..dd27a00d 100644
--- a/src/lib/blib.h
+++ b/src/lib/blib.h
@@ -6,6 +6,7 @@
void print(const char *fmt, ...);
char getchar(void);
void gets(char *buf, size_t limit);
+uint64_t strtoui(const char *s);
#define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
diff --git a/src/lib/config.c b/src/lib/config.c
new file mode 100644
index 00000000..5aebb806
--- /dev/null
+++ b/src/lib/config.c
@@ -0,0 +1,30 @@
+#include <stddef.h>
+#include <lib/config.h>
+#include <lib/libc.h>
+
+#define SEPARATOR '\n'
+
+char *config_get_value(char *buf, size_t limit, const char *config, const char *key) {
+ if (!limit || !buf)
+ return NULL;
+
+ size_t key_len = strlen(key);
+
+ for (size_t i = 0; config[i]; i++) {
+ if (!strncmp(&config[i], key, key_len) && config[i + key_len] == '=') {
+ if (i && config[i - 1] != SEPARATOR)
+ continue;
+ i += key_len + 1;
+ size_t j;
+ for (j = 0; config[i + j] != SEPARATOR && config[i + j]; j++) {
+ if (j == limit - 1)
+ break;
+ buf[j] = config[i + j];
+ }
+ buf[j] = 0;
+ return buf;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/lib/config.h b/src/lib/config.h
new file mode 100644
index 00000000..0f486a2f
--- /dev/null
+++ b/src/lib/config.h
@@ -0,0 +1,8 @@
+#ifndef __LIB__CONFIG_H__
+#define __LIB__CONFIG_H__
+
+#include <stddef.h>
+
+char *config_get_value(char *buf, size_t limit, const char *config, const char *key);
+
+#endif
diff --git a/src/main.c b/src/main.c
index 449d38c1..bb7b412a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,12 +9,15 @@ asm (
#include <lib/real.h>
#include <lib/blib.h>
#include <lib/mbr.h>
+#include <lib/config.h>
#include <fs/echfs.h>
+#define CONFIG_NAME "qloader2.cfg"
+
extern symbol bss_begin;
extern symbol bss_end;
-#define QWORD_KERNEL "qword.bin"
+static int config_loaded = 0;
void main(int boot_drive) {
// Zero out .bss section
@@ -24,30 +27,49 @@ void main(int boot_drive) {
// Initial prompt.
init_vga_textmode();
print("qLoader 2\n\n");
- print("=> Boot drive: %x\n\n", boot_drive);
+ print("=> Boot drive: %x\n", boot_drive);
// Enumerate partitions.
struct mbr_part parts[4];
for (int i = 0; i < 4; i++) {
- print("=> Checking for partition %d...", i);
+ print("=> Checking for partition %d...\n", i);
int ret = mbr_get_part(&parts[i], boot_drive, i);
if (ret) {
- print("Not found!\n");
+ print(" Not found!\n");
} else {
- print("Found!\n");
+ print(" Found!\n");
+ if (!config_loaded) {
+ if (!load_echfs_file(boot_drive, i, (void *)0x100000, CONFIG_NAME)) {
+ config_loaded = 1;
+ print(" Config file found and loaded!\n");
+ }
+ }
}
}
- // Load the file from the chooen partition at 1 MiB.
- int part = 1; // TODO: The boot partition is hardcoded for now.
- print("=> Booting %s in partition %d\n", QWORD_KERNEL, part);
- load_echfs_file(boot_drive, part, (void *)0x100000, QWORD_KERNEL);
+ int drive, part;
+ char path[128], cmdline[128];
+
+ if (config_loaded) {
+ char buf[32];
+ config_get_value(buf, 32, (void*)0x100000, "KERNEL_DRIVE");
+ drive = (int)strtoui(buf);
+ config_get_value(buf, 32, (void*)0x100000, "KERNEL_PARTITION");
+ part = (int)strtoui(buf);
+ config_get_value(path, 128, (void*)0x100000, "KERNEL_PATH");
+ config_get_value(cmdline, 128, (void*)0x100000, "KERNEL_CMDLINE");
+ } else {
+ print(" !! NO CONFIG FILE FOUND ON BOOT DRIVE !!");
+ for (;;);
+ }
+
+ load_echfs_file(drive, part, (void *)0x100000, path);
// Boot the kernel.
asm volatile (
"jmp 0x100000"
:
- : "b" ("")
+ : "b" (cmdline)
: "memory"
);
}
