2020-01-22 09:13:19 +03:00
|
|
|
#include <stddef.h>
|
2020-10-17 06:37:39 +03:00
|
|
|
#include <stdbool.h>
|
2020-01-22 09:13:19 +03:00
|
|
|
#include <lib/config.h>
|
|
|
|
#include <lib/libc.h>
|
2020-03-30 22:24:36 +03:00
|
|
|
#include <lib/blib.h>
|
2020-09-20 13:03:44 +03:00
|
|
|
#include <mm/pmm.h>
|
2020-04-14 06:20:55 +03:00
|
|
|
#include <fs/file.h>
|
2020-11-05 03:37:45 +03:00
|
|
|
#include <lib/print.h>
|
|
|
|
#include <pxe/tftp.h>
|
2020-01-22 09:13:19 +03:00
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
#include <sys/cpu.h>
|
|
|
|
|
2020-01-22 09:13:19 +03:00
|
|
|
#define SEPARATOR '\n'
|
|
|
|
|
2020-10-20 03:38:44 +03:00
|
|
|
bool config_ready = false;
|
|
|
|
|
2020-03-30 22:24:36 +03:00
|
|
|
static char *config_addr;
|
|
|
|
|
2020-11-05 03:37:45 +03:00
|
|
|
int init_config_disk(struct part *part) {
|
2020-04-14 06:20:55 +03:00
|
|
|
struct file_handle f;
|
2020-03-30 22:24:36 +03:00
|
|
|
|
2020-11-02 12:17:20 +03:00
|
|
|
if (fopen(&f, part, "/limine.cfg")) {
|
|
|
|
if (fopen(&f, part, "/boot/limine.cfg")) {
|
2020-04-23 23:23:38 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2020-03-30 22:24:36 +03:00
|
|
|
}
|
|
|
|
|
2020-07-02 17:20:18 +03:00
|
|
|
size_t config_size = f.size + 1;
|
2020-09-20 13:03:44 +03:00
|
|
|
config_addr = conv_mem_alloc(config_size);
|
2020-03-30 22:24:36 +03:00
|
|
|
|
2020-04-14 06:20:55 +03:00
|
|
|
fread(&f, config_addr, 0, f.size);
|
2020-03-30 22:24:36 +03:00
|
|
|
|
2020-11-05 03:37:45 +03:00
|
|
|
return init_config(config_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int init_config_pxe(void) {
|
|
|
|
struct tftp_file_handle cfg;
|
|
|
|
if (tftp_open(&cfg, 0, 69, "limine.cfg")) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
config_addr = conv_mem_alloc(cfg.file_size);
|
|
|
|
tftp_read(&cfg, config_addr, 0, cfg.file_size);
|
|
|
|
|
|
|
|
print("\nconfig: %s\n", config_addr);
|
|
|
|
|
|
|
|
return init_config(cfg.file_size);
|
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
#define NOT_CHILD (-1)
|
|
|
|
#define DIRECT_CHILD 0
|
|
|
|
#define INDIRECT_CHILD 1
|
|
|
|
|
|
|
|
static int is_child(char *buf, size_t limit,
|
|
|
|
size_t current_depth, size_t index) {
|
|
|
|
if (!config_get_entry_name(buf, index, limit))
|
|
|
|
return NOT_CHILD;
|
|
|
|
if (strlen(buf) < current_depth + 1)
|
|
|
|
return NOT_CHILD;
|
|
|
|
for (size_t j = 0; j < current_depth; j++)
|
|
|
|
if (buf[j] != ':')
|
|
|
|
return NOT_CHILD;
|
|
|
|
if (buf[current_depth] == ':')
|
|
|
|
return INDIRECT_CHILD;
|
|
|
|
return DIRECT_CHILD;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_directory(char *buf, size_t limit,
|
|
|
|
size_t current_depth, size_t index) {
|
|
|
|
switch (is_child(buf, limit, current_depth + 1, index + 1)) {
|
|
|
|
default:
|
|
|
|
case NOT_CHILD:
|
|
|
|
return false;
|
|
|
|
case INDIRECT_CHILD:
|
|
|
|
panic("config: Malformed config file. Parentless child.");
|
|
|
|
case DIRECT_CHILD:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct menu_entry *create_menu_tree(struct menu_entry *parent,
|
|
|
|
size_t current_depth, size_t index) {
|
|
|
|
struct menu_entry *root = NULL, *prev = NULL;
|
|
|
|
|
|
|
|
for (size_t i = index; ; i++) {
|
|
|
|
static char name[64];
|
|
|
|
|
|
|
|
switch (is_child(name, 64, current_depth, i)) {
|
|
|
|
case NOT_CHILD:
|
|
|
|
return root;
|
|
|
|
case INDIRECT_CHILD:
|
|
|
|
continue;
|
|
|
|
case DIRECT_CHILD:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct menu_entry *entry = conv_mem_alloc(sizeof(struct menu_entry));
|
|
|
|
|
|
|
|
if (root == NULL)
|
|
|
|
root = entry;
|
|
|
|
|
|
|
|
config_get_entry_name(name, i, 64);
|
|
|
|
|
|
|
|
strcpy(entry->name, name + current_depth);
|
|
|
|
entry->parent = parent;
|
|
|
|
|
|
|
|
if (is_directory(name, 64, current_depth, i)) {
|
|
|
|
entry->sub = create_menu_tree(entry, current_depth + 1, i + 1);
|
|
|
|
} else {
|
|
|
|
size_t entry_size;
|
|
|
|
char *config_entry = config_get_entry(&entry_size, i);
|
|
|
|
entry->body = conv_mem_alloc(entry_size + 1);
|
|
|
|
memcpy(entry->body, config_entry, entry_size);
|
|
|
|
entry->body[entry_size] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prev != NULL)
|
|
|
|
prev->next = entry;
|
|
|
|
prev = entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct menu_entry *menu_tree = NULL;
|
|
|
|
|
2020-11-05 03:37:45 +03:00
|
|
|
int init_config(size_t config_size) {
|
2020-07-02 03:51:06 +03:00
|
|
|
// remove windows carriage returns, if any
|
2020-07-02 17:14:09 +03:00
|
|
|
for (size_t i = 0; i < config_size; i++) {
|
2020-07-02 03:51:06 +03:00
|
|
|
if (config_addr[i] == '\r') {
|
2020-07-02 17:14:09 +03:00
|
|
|
for (size_t j = i; j < config_size - 1; j++)
|
2020-07-02 03:51:06 +03:00
|
|
|
config_addr[j] = config_addr[j+1];
|
2020-07-02 17:14:09 +03:00
|
|
|
config_size--;
|
2020-07-02 03:51:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
menu_tree = create_menu_tree(NULL, 1, 0);
|
|
|
|
|
2020-10-20 03:38:44 +03:00
|
|
|
config_ready = true;
|
|
|
|
|
2020-03-30 22:24:36 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
bool config_get_entry_name(char *ret, size_t index, size_t limit) {
|
2020-04-21 17:23:30 +03:00
|
|
|
char *p = config_addr;
|
|
|
|
|
|
|
|
for (size_t i = 0; i <= index; i++) {
|
|
|
|
while (*p != ':') {
|
|
|
|
if (!*p)
|
2020-11-17 01:31:03 +03:00
|
|
|
return false;
|
2020-04-21 17:23:30 +03:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
p++;
|
2020-05-27 10:24:59 +03:00
|
|
|
if ((p - 1) != config_addr && *(p - 2) != '\n')
|
2020-04-24 18:28:19 +03:00
|
|
|
i--;
|
2020-04-21 17:23:30 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
p--;
|
|
|
|
|
2020-04-21 17:23:30 +03:00
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < (limit - 1); i++) {
|
|
|
|
if (p[i] == SEPARATOR)
|
|
|
|
break;
|
|
|
|
ret[i] = p[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
ret[i] = 0;
|
2020-11-17 01:31:03 +03:00
|
|
|
return true;
|
2020-04-21 17:23:30 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
char *config_get_entry(size_t *size, size_t index) {
|
|
|
|
char *ret;
|
2020-04-21 17:23:30 +03:00
|
|
|
char *p = config_addr;
|
|
|
|
|
|
|
|
for (size_t i = 0; i <= index; i++) {
|
|
|
|
while (*p != ':') {
|
|
|
|
if (!*p)
|
2020-11-17 01:31:03 +03:00
|
|
|
return NULL;
|
2020-04-21 17:23:30 +03:00
|
|
|
p++;
|
|
|
|
}
|
2020-04-21 19:27:05 +03:00
|
|
|
p++;
|
2020-05-27 10:24:59 +03:00
|
|
|
if ((p - 1) != config_addr && *(p - 2) != '\n')
|
2020-04-24 18:02:53 +03:00
|
|
|
i--;
|
2020-04-21 17:23:30 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
do {
|
|
|
|
p++;
|
|
|
|
} while (*p != '\n');
|
|
|
|
|
|
|
|
ret = p;
|
2020-04-21 17:23:30 +03:00
|
|
|
|
2020-04-24 18:28:19 +03:00
|
|
|
cont:
|
2020-04-21 19:27:05 +03:00
|
|
|
while (*p != ':' && *p)
|
|
|
|
p++;
|
2020-04-21 17:23:30 +03:00
|
|
|
|
2020-04-24 18:36:37 +03:00
|
|
|
if (*p && *(p - 1) != '\n') {
|
|
|
|
p++;
|
2020-04-24 18:28:19 +03:00
|
|
|
goto cont;
|
2020-04-24 18:36:37 +03:00
|
|
|
}
|
2020-04-24 18:28:19 +03:00
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
*size = p - ret;
|
2020-04-21 17:23:30 +03:00
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
return ret;
|
2020-04-21 17:23:30 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
char *config_get_value(const char *config,
|
|
|
|
char *buf, size_t index, size_t limit, const char *key) {
|
2020-03-30 22:24:36 +03:00
|
|
|
if (!limit || !buf || !key)
|
2020-01-22 09:13:19 +03:00
|
|
|
return NULL;
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
if (config == NULL)
|
|
|
|
config = config_addr;
|
|
|
|
|
2020-01-22 09:13:19 +03:00
|
|
|
size_t key_len = strlen(key);
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
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)
|
2020-01-22 09:13:19 +03:00
|
|
|
continue;
|
2020-03-30 23:27:15 +03:00
|
|
|
if (index--)
|
|
|
|
continue;
|
2020-01-22 09:13:19 +03:00
|
|
|
i += key_len + 1;
|
|
|
|
size_t j;
|
2020-11-17 01:31:03 +03:00
|
|
|
for (j = 0; config[i + j] != SEPARATOR && config[i + j]; j++) {
|
2020-01-22 09:13:19 +03:00
|
|
|
if (j == limit - 1)
|
|
|
|
break;
|
2020-11-17 01:31:03 +03:00
|
|
|
buf[j] = config[i + j];
|
2020-01-22 09:13:19 +03:00
|
|
|
}
|
|
|
|
buf[j] = 0;
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|