kernel_args: redo implementation

This commit is contained in:
Matheus
2025-09-07 23:09:34 -03:00
parent a3a51abfed
commit 80786cf97a
15 changed files with 198 additions and 107 deletions
+4 -2
View File
@@ -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;
+7
View File
@@ -48,6 +48,13 @@ SECTIONS
*(.data .data.*);
} :data
. = ALIGN(8);
.kernel_arguments : {
kernel_arguments = .;
*(.kernel_arguments);
kernel_arguments_end = .;
} :data
. = ALIGN(8);
.bss : {
*(COMMON)
+4 -2
View File
@@ -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
+6 -4
View File
@@ -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 -2
View File
@@ -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;
-7
View File
@@ -1,7 +0,0 @@
#ifndef _CMDLINE_H
#define _CMDLINE_H
char *cmdline_get(char *);
void cmdline_parse();
#endif
+57
View File
@@ -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
+1
View File
@@ -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
+13
View File
@@ -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
View File
@@ -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
-77
View File
@@ -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;
}
}
+82
View File
@@ -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);
}
+4 -2
View File
@@ -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");
-1
View File
@@ -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>
+4 -2
View File
@@ -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;
}