mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel_args: redo implementation
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include <kernel/vmm.h>
|
||||
#include <kernel/interrupt.h>
|
||||
#include <arch/tsc.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
|
||||
#include <uacpi/acpi.h>
|
||||
#include <uacpi/tables.h>
|
||||
@@ -61,8 +61,10 @@ static void counterirq(isr_t *isr, context_t *context) {
|
||||
write64(HPET_REG_CONFIG, 1 + ((hpet_private.type == TYPE_LEGACY) ? 2 : 0));
|
||||
}
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(nohpet, bool);
|
||||
|
||||
static bool hpet_probe(void) {
|
||||
if (cmdline_get("nohpet"))
|
||||
if (GET_KERNEL_ARGUMENT(nohpet, bool))
|
||||
return false;
|
||||
|
||||
bool usable = false;
|
||||
|
||||
@@ -48,6 +48,13 @@ SECTIONS
|
||||
*(.data .data.*);
|
||||
} :data
|
||||
|
||||
. = ALIGN(8);
|
||||
.kernel_arguments : {
|
||||
kernel_arguments = .;
|
||||
*(.kernel_arguments);
|
||||
kernel_arguments_end = .;
|
||||
} :data
|
||||
|
||||
. = ALIGN(8);
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <arch/cpuid.h>
|
||||
#include <kernel/pmm.h>
|
||||
#include <arch/tsc.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
|
||||
#define KVM_TIMER_SYSTEM_TIME_ALIGNMENT 4
|
||||
#define KVM_TIMER_SYSTEM_TIME_ENABLE 1
|
||||
@@ -23,8 +23,10 @@ typedef struct {
|
||||
uint8_t padding1[2];
|
||||
} __attribute__((packed)) kvm_timer_info_t;
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(nokvmclock, bool);
|
||||
|
||||
static bool kvm_timer_probe(void) {
|
||||
if (cmdline_get("nokvmclock"))
|
||||
if (GET_KERNEL_ARGUMENT(nokvmclock, bool))
|
||||
return false;
|
||||
|
||||
// figure out if we are running in kvm
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/gdt.h>
|
||||
#include <arch/idt.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
#include <arch/smp.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <kernel/init.h>
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(nosmp, bool);
|
||||
|
||||
static volatile struct limine_smp_request smprequest = {
|
||||
.id = LIMINE_SMP_REQUEST
|
||||
};
|
||||
@@ -58,8 +60,8 @@ void arch_smp_haltallothers(void) {
|
||||
}
|
||||
|
||||
size_t arch_smp_get_cpu_count(void) {
|
||||
//if (cmdline_get("nosmp"))
|
||||
// return 1;
|
||||
if (GET_KERNEL_ARGUMENT(nosmp, bool))
|
||||
return 1;
|
||||
|
||||
struct limine_smp_response *response = smprequest.response;
|
||||
if (response == NULL)
|
||||
@@ -95,7 +97,7 @@ void arch_smp_wakeup(void) {
|
||||
smp_cpus = alloc(response->cpu_count * sizeof(cpu_t *));
|
||||
__assert(smp_cpus);
|
||||
|
||||
void (*wakeupfn)(struct limine_smp_info *) = cpuwakeup;//cmdline_get("nosmp") ? cpuwakeuphalt : cpuwakeup;
|
||||
void (*wakeupfn)(struct limine_smp_info *) = GET_KERNEL_ARGUMENT(nosmp, bool) ? cpuwakeuphalt : cpuwakeup;
|
||||
|
||||
// make the other processors jump to cpuwakeup()
|
||||
for (int i = 0; i < response->cpu_count; ++i) {
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include <logging.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <arch/hpet.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(notsc, bool);
|
||||
|
||||
static bool tsc_probe(void) {
|
||||
if (cmdline_get("notsc"))
|
||||
if (GET_KERNEL_ARGUMENT(notsc, bool))
|
||||
return false;
|
||||
|
||||
cpuid_results_t cpuid_results;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef _CMDLINE_H
|
||||
#define _CMDLINE_H
|
||||
|
||||
char *cmdline_get(char *);
|
||||
void cmdline_parse();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef _KERNEL_ARGS_H
|
||||
#define _KERNEL_ARGS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void kernel_arguments_parse(void);
|
||||
|
||||
#define KERNEL_ARGUMENT_TYPE_BOOL 0
|
||||
#define KERNEL_ARGUMENT_TYPE_STR 1
|
||||
#define KERNEL_ARGUMENT_TYPE_INT 2
|
||||
|
||||
typedef struct {
|
||||
const char *key;
|
||||
int type;
|
||||
bool found;
|
||||
union {
|
||||
char *value_str;
|
||||
uint64_t value_int;
|
||||
};
|
||||
} kernel_argument_t;
|
||||
|
||||
#define DEFINE_KERNEL_ARGUMENT(name, t) \
|
||||
static kernel_argument_t kernel_argument_##name = { \
|
||||
.key = #name , \
|
||||
.type = _Generic((t)0, \
|
||||
uint8_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
uint16_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
uint32_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
uint64_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
int8_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
int16_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
int32_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
int64_t: KERNEL_ARGUMENT_TYPE_INT, \
|
||||
bool: KERNEL_ARGUMENT_TYPE_BOOL, \
|
||||
char *: KERNEL_ARGUMENT_TYPE_STR, \
|
||||
default: (kernel_argument_t *)NULL \
|
||||
), \
|
||||
.found = false \
|
||||
}; \
|
||||
__attribute__((section(".kernel_arguments"), used)) static kernel_argument_t *kernel_argument_ptr_##name = &kernel_argument_##name;
|
||||
|
||||
#define GET_KERNEL_ARGUMENT(name, t) _Generic((t)0, \
|
||||
uint8_t: kernel_argument_##name.value_int, \
|
||||
uint16_t: kernel_argument_##name.value_int, \
|
||||
uint32_t: kernel_argument_##name.value_int, \
|
||||
uint64_t: kernel_argument_##name.value_int, \
|
||||
int8_t: kernel_argument_##name.value_int, \
|
||||
int16_t: kernel_argument_##name.value_int, \
|
||||
int32_t: kernel_argument_##name.value_int, \
|
||||
int64_t: kernel_argument_##name.value_int, \
|
||||
bool: kernel_argument_##name.found, \
|
||||
char *: kernel_argument_##name.value_str, \
|
||||
default: (kernel_argument_t *)NULL \
|
||||
)
|
||||
|
||||
#endif
|
||||
@@ -13,5 +13,6 @@ int strncmp(const char *a, const char *b, size_t c);
|
||||
int memcmp(const void *a, const void *b, size_t s);
|
||||
void *memmove(void *_d, const void *_s, size_t c);
|
||||
char *strerror(int errno);
|
||||
long long atoll(const char *c);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -99,6 +99,19 @@ void *memmove(void *_d, const void *_s, size_t c) {
|
||||
return _d;
|
||||
}
|
||||
|
||||
long long atoll(const char *c) {
|
||||
char first = *c;
|
||||
if (first == '-')
|
||||
++c;
|
||||
|
||||
int v = 0;
|
||||
|
||||
while (*c)
|
||||
v = v * 10 + (*c++) - '0';
|
||||
|
||||
return first == '-' ? -v : v;
|
||||
}
|
||||
|
||||
#define DO_NAME(e) \
|
||||
case e: \
|
||||
return #e;
|
||||
|
||||
+12
-8
@@ -1,7 +1,7 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel/init.h>
|
||||
#include <logging.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
#include <kernel/vfs.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <kernel/initrd.h>
|
||||
@@ -9,27 +9,31 @@
|
||||
|
||||
static cpu_t bsp_cpu;
|
||||
|
||||
INIT_ROUTINE_DEFINE(bsp_early,
|
||||
INIT_ROUTINE_FLAGS_PHONY,
|
||||
INIT_ROUTINE_DEFINE(bsp_early,
|
||||
INIT_ROUTINE_FLAGS_PHONY,
|
||||
NULL,
|
||||
alloc, term, cpu
|
||||
);
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(root, char *);
|
||||
DEFINE_KERNEL_ARGUMENT(rootfs, char *);
|
||||
DEFINE_KERNEL_ARGUMENT(initrd, bool);
|
||||
|
||||
void kernel_entry() {
|
||||
cpu_set(&bsp_cpu);
|
||||
logging_sethook(arch_early_log);
|
||||
|
||||
init_run_routine(INIT_GET_ROUTINE(bsp_early));
|
||||
kernel_arguments_parse();
|
||||
|
||||
cmdline_parse();
|
||||
init_run_routine(INIT_GET_ROUTINE(bsp_early));
|
||||
|
||||
init_run_all_routines();
|
||||
|
||||
// kernel is fully up and running by now
|
||||
// mount root filesystem
|
||||
|
||||
char *root = cmdline_get("root");
|
||||
char *rootfs = cmdline_get("rootfs");
|
||||
char *root = GET_KERNEL_ARGUMENT(root, char *);
|
||||
char *rootfs = GET_KERNEL_ARGUMENT(rootfs, char *);
|
||||
|
||||
printf("entry: mounting %s (%s) on /\n", root == NULL ? "none" : root, rootfs);
|
||||
|
||||
@@ -46,7 +50,7 @@ void kernel_entry() {
|
||||
VOP_RELEASE(backing);
|
||||
}
|
||||
|
||||
if (cmdline_get("initrd"))
|
||||
if (GET_KERNEL_ARGUMENT(initrd, bool))
|
||||
initrd_unpack();
|
||||
|
||||
// spawn init
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <hashtable.h>
|
||||
#include <limine.h>
|
||||
#include <logging.h>
|
||||
|
||||
static volatile struct limine_kernel_file_request kernel_file_request = {
|
||||
.id = LIMINE_KERNEL_FILE_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
static hashtable_t pair_table;
|
||||
|
||||
char *cmdline_get(char *key) {
|
||||
void *v;
|
||||
return hashtable_get(&pair_table, &v, key, strlen(key)) == 0 ? v : NULL;
|
||||
}
|
||||
|
||||
void cmdline_parse() {
|
||||
__assert(hashtable_init(&pair_table, 16) == 0);
|
||||
__assert(kernel_file_request.response);
|
||||
struct limine_file *kernel_file = kernel_file_request.response->kernel_file;
|
||||
__assert(kernel_file);
|
||||
char *cmdline = kernel_file->cmdline;
|
||||
__assert(cmdline);
|
||||
|
||||
size_t buffer_len = strlen(cmdline) + 1;
|
||||
char buffer[buffer_len];
|
||||
memset(buffer, 0, buffer_len);
|
||||
char *cmdline_ptr = cmdline;
|
||||
char *buffer_ptr = buffer;
|
||||
|
||||
bool do_convert = true;
|
||||
|
||||
while (*cmdline_ptr) {
|
||||
char cmd_char = *cmdline_ptr++;
|
||||
if (cmd_char == ' ' && do_convert)
|
||||
*buffer_ptr++ = '\0';
|
||||
else if (cmd_char == '"') {
|
||||
do_convert = !do_convert;
|
||||
--buffer_len;
|
||||
} else
|
||||
*buffer_ptr++ = cmd_char;
|
||||
}
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
|
||||
int i = 0;
|
||||
while (i < buffer_len) {
|
||||
char *iterator = &buffer[i];
|
||||
bool pair = false;
|
||||
while (*iterator) {
|
||||
if (*iterator == '=') {
|
||||
pair = true;
|
||||
*iterator = '\0';
|
||||
}
|
||||
++iterator;
|
||||
}
|
||||
|
||||
size_t key_len = strlen(&buffer[i]);
|
||||
if (pair) {
|
||||
char *value_ptr = &buffer[i + key_len + 1];
|
||||
size_t value_len = strlen(value_ptr);
|
||||
|
||||
char *value = alloc(value_len) + 1;
|
||||
__assert(value);
|
||||
strcpy(value, value_ptr);
|
||||
__assert(hashtable_set(&pair_table, value, &buffer[i], key_len, true) == 0);
|
||||
i += value_len + 1;
|
||||
} else {
|
||||
char *value = alloc(key_len + 1);
|
||||
__assert(value);
|
||||
strcpy(value, &buffer[i]);
|
||||
__assert(hashtable_set(&pair_table, value, &buffer[i], key_len, true) == 0);
|
||||
}
|
||||
i += key_len + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <kernel/kernel_args.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <hashtable.h>
|
||||
#include <limine.h>
|
||||
#include <logging.h>
|
||||
|
||||
#define TOTAL_ARGUMENTS_CHARACTER_LIMIT 4096
|
||||
|
||||
static volatile struct limine_kernel_file_request kernel_file_request = {
|
||||
.id = LIMINE_KERNEL_FILE_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
static size_t allocated = 0;
|
||||
static char argument_buffer[TOTAL_ARGUMENTS_CHARACTER_LIMIT];
|
||||
|
||||
extern kernel_argument_t *kernel_arguments[];
|
||||
extern kernel_argument_t *kernel_arguments_end[];
|
||||
|
||||
static void insert_argument(const char *key, const char *value) {
|
||||
size_t argument_count = ((uintptr_t)kernel_arguments_end - (uintptr_t)kernel_arguments) / sizeof(kernel_argument_t *);
|
||||
char *buffer = &argument_buffer[allocated];
|
||||
if (value) {
|
||||
strcpy(buffer, value);
|
||||
allocated += strlen(value) + 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < argument_count; ++i) {
|
||||
if (strcmp(kernel_arguments[i]->key, key))
|
||||
continue;
|
||||
|
||||
kernel_arguments[i]->found = true;
|
||||
|
||||
switch (kernel_arguments[i]->type) {
|
||||
case KERNEL_ARGUMENT_TYPE_STR:
|
||||
kernel_arguments[i]->value_str = value ? buffer : NULL;
|
||||
break;
|
||||
case KERNEL_ARGUMENT_TYPE_INT:
|
||||
kernel_arguments[i]->value_int = value ? atoll(buffer) : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_arguments_parse(void) {
|
||||
__assert(kernel_file_request.response);
|
||||
const char *cmdline = kernel_file_request.response->kernel_file->cmdline;
|
||||
__assert(cmdline);
|
||||
size_t length = min(strlen(cmdline), TOTAL_ARGUMENTS_CHARACTER_LIMIT);
|
||||
char temp_buffer[length];
|
||||
memcpy(temp_buffer, cmdline, length);
|
||||
|
||||
bool escaping = false;
|
||||
const char *key = temp_buffer[0] == ' ' ? NULL : temp_buffer;
|
||||
const char *value = NULL;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (temp_buffer[i] == '"') {
|
||||
escaping = !escaping;
|
||||
temp_buffer[i] = '\0';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (temp_buffer[i] == '=') {
|
||||
value = &temp_buffer[i + 1];
|
||||
temp_buffer[i] = '\0';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (temp_buffer[i] == ' ' && !escaping) {
|
||||
temp_buffer[i] = '\0';
|
||||
|
||||
if (key)
|
||||
insert_argument(key, value);
|
||||
|
||||
key = &temp_buffer[i + 1];
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (key != temp_buffer + length)
|
||||
insert_argument(key, value);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/elf.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
|
||||
static hashtable_t pid_table;
|
||||
static scache_t *processcache;
|
||||
@@ -292,6 +292,8 @@ void proc_exit(void) {
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(initarg, char *);
|
||||
|
||||
void proc_run_init() {
|
||||
printf("proc: loading /init\n");
|
||||
|
||||
@@ -358,7 +360,7 @@ void proc_run_init() {
|
||||
proc->root = vfsroot;
|
||||
VOP_HOLD(vfsroot);
|
||||
|
||||
char *argv[] = {"/init", cmdline_get("initarg"), NULL};
|
||||
char *argv[] = {"/init", GET_KERNEL_ARGUMENT(initarg, char *), NULL};
|
||||
char *envp[] = {NULL};
|
||||
|
||||
void *stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp, "/init");
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <semaphore.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <kernel/jobctl.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/auth.h>
|
||||
#include <arch/smp.h>
|
||||
#include <kernel/init.h>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/cmdline.h>
|
||||
#include <kernel/kernel_args.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
DEFINE_KERNEL_ARGUMENT(nomultithread, bool);
|
||||
|
||||
syscallret_t syscall_newthread(context_t *, void *entry, void *stack) {
|
||||
syscallret_t ret = {
|
||||
.ret = -1
|
||||
@@ -11,7 +13,7 @@ syscallret_t syscall_newthread(context_t *, void *entry, void *stack) {
|
||||
|
||||
// TODO perhaps clean up threads here as well
|
||||
// if the kernel was specified to have no user threading in the cmdline
|
||||
if (cmdline_get("nomultithread")) {
|
||||
if (GET_KERNEL_ARGUMENT(nomultithread, bool)) {
|
||||
ret.errno = ENOSYS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user