summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2025-07-30 14:32:01 -0400
committerJon Santmyer <jon@jonsantmyer.com>2025-07-30 14:32:01 -0400
commitb905869a35f062a4e5072f10bec3a2ba3db0e365 (patch)
tree0666691804878857b4bb07daca8a54f5ddb8ae0b /device
downloadjove-kernel-b905869a35f062a4e5072f10bec3a2ba3db0e365.tar.gz
jove-kernel-b905869a35f062a4e5072f10bec3a2ba3db0e365.tar.bz2
jove-kernel-b905869a35f062a4e5072f10bec3a2ba3db0e365.zip
working userland with some invoke syscalls
Diffstat (limited to 'device')
-rw-r--r--device/initrd.c116
-rw-r--r--device/portio_uart.c68
-rw-r--r--device/uart.c13
3 files changed, 197 insertions, 0 deletions
diff --git a/device/initrd.c b/device/initrd.c
new file mode 100644
index 0000000..36eefc6
--- /dev/null
+++ b/device/initrd.c
@@ -0,0 +1,116 @@
+#if defined(ENABLE_INITRD)
+
+#include <stddef.h>
+
+#include "device/initrd.h"
+#include "device/processor.h"
+#include "object.h"
+#include "jove.h"
+#include "bootargs.h"
+#include "print.h"
+#include "string.h"
+#include "panic.h"
+
+struct jove_ObjectDirectory s_initrd_dir = {
+ .entries = {
+ [0] = (objdir_entry_t){
+ .type = KO_OBJECT_DIRECTORY,
+ .data = 1
+ }
+ }
+};
+
+static uintptr_t s_initrd_getaddr(char *path);
+
+#if defined(__limine__)
+
+#include "boot/limine/limine.h"
+static struct limine_module_request s_module_request = {
+ .id = LIMINE_MODULE_REQUEST
+};
+
+static uintptr_t
+s_initrd_getaddr(char *path)
+{
+ struct limine_module_response *response = s_module_request.response;
+ for(size_t i = 0; i < response->module_count; i++) {
+ struct limine_file *module = response->modules[i];
+ if(strcmp(path, module->path) == 0)
+ return (uintptr_t)module->address;
+ }
+ kpanic("Failed to load module at path %s\n", path);
+}
+
+
+#endif
+
+static size_t
+s_tar_oct_dec(const char *oct)
+{
+ size_t r = 0;
+ for(; *oct; oct++) r = (r * 8) + (*oct - '0');
+ return r;
+}
+
+void
+tar_parse(tar_block_t *block)
+{
+ while(true) {
+ tar_header_t *header = &block->header;
+ if(*header->name == 0) return;
+ if(s_initrd_dir.self.data == OBJECT_DIRECTORY_MAX_ENTRIES) {
+ klogf("More than %i files in initrd! Skipping the rest.\n", OBJECT_DIRECTORY_MAX_ENTRIES - 1);
+ }
+
+ size_t file_size = s_tar_oct_dec(header->size);
+ s_initrd_dir.entries[s_initrd_dir.self.data++] = (objdir_entry_t) {
+ .type = KO_INITRD_FILE,
+ .data = (uintptr_t)block
+ };
+
+ klogf("Load file '%s' at %p size %x\n", block->header.name, block + 1, file_size);
+
+ block = &block[(file_size / 512) + 1];
+ if(file_size % 512) block++;
+ }
+}
+
+void
+initrd_setup(void)
+{
+ char *initrd_path = bootargs_getarg("initrd");
+ if(initrd_path == 0) {
+ kpanic("Missing kernel commandline argument for initrd.");
+ }
+
+ uintptr_t initrd_addr = s_initrd_getaddr(initrd_path);
+ klogf("Initrd found at %p\n", initrd_addr);
+ tar_parse((tar_block_t*)initrd_addr);
+
+ size_t initrd_diri = _initDirectory.self.data++;
+ _initDirectory.entries[initrd_diri] = (objdir_entry_t) {
+ .type = KO_OBJECT_DIRECTORY,
+ .data = (uintptr_t)&s_initrd_dir
+ };
+ //Add initrd dir to init object
+ ((init_data_t*)_initDirectory.entries[1].data)->initrd_dir = initrd_diri;
+}
+
+int
+initrd_file_size(tar_header_t *file)
+{
+ return s_tar_oct_dec(file->size);
+}
+
+tar_header_t*
+initrd_find_file(const char *filename)
+{
+ for(size_t i = 0; i < s_initrd_dir.self.data - 1; i++) {
+ objdir_entry_t *entry = &s_initrd_dir.entries[i+1];
+ tar_header_t *file = (tar_header_t*)entry->data;
+ if(strcmp(file->name + 1, filename) == 0) return file;
+ }
+ return NULL;
+}
+
+#endif
diff --git a/device/portio_uart.c b/device/portio_uart.c
new file mode 100644
index 0000000..00800b5
--- /dev/null
+++ b/device/portio_uart.c
@@ -0,0 +1,68 @@
+#ifdef ENABLE_PORTIO_UART
+#include "jove.h"
+#include "device/portio_uart.h"
+#include "device/portio.h"
+
+static void
+s_set_int(ioport_t dev, uint8_t enable)
+{
+ port_outb(PORTIO_UART_COM_IER(dev), enable);
+}
+
+static void
+s_set_baud(ioport_t dev, uint16_t baud)
+{
+ /* Enable DLAB */
+ port_outb(PORTIO_UART_COM_LCR(dev), PORTIO_UART_COM_LCR(dev) | 0x80);
+ /* Write low & high. */
+ port_outb(PORTIO_UART_COM_DLAB_DLL(dev), (uint8_t)(baud & 0xFF));
+ port_outb(PORTIO_UART_COM_DLAB_DLH(dev), (uint8_t)((baud >> 8) & 0xFF));
+ /* Disable DLAB */
+ port_outb(PORTIO_UART_COM_LCR(dev), PORTIO_UART_COM_LCR(dev) & 0x7F);
+}
+
+static void
+s_set_fcr(ioport_t dev, uint8_t flg)
+{
+ port_outb(PORTIO_UART_COM_FCR(dev), flg);
+}
+
+static void
+s_set_lcr(ioport_t dev, uint8_t flg)
+{
+ port_outb(PORTIO_UART_COM_LCR(dev), flg);
+}
+
+static void
+s_set_mcr(ioport_t dev, uint8_t flg)
+{
+ port_outb(PORTIO_UART_COM_MCR(dev), flg);
+}
+
+void
+portio_uart_setup(void)
+{
+ s_set_int(PORTIO_UART_COM1, 0);
+ s_set_baud(PORTIO_UART_COM1, 3);
+ s_set_lcr(PORTIO_UART_COM1, 1 | 2);
+ s_set_fcr(PORTIO_UART_COM1, 1 | 2 | 4 | 0xC0);
+ s_set_fcr(PORTIO_UART_COM1, 1 | 2 | 8);
+ s_set_mcr(PORTIO_UART_COM1, 1 | 2 | 4 | 8);
+
+ uint64_t serial_i = _initDirectory.self.data++;
+ _initDirectory.entries[serial_i] = (struct jove_ObjectDirectoryEntry) {
+ .type = KO_DEV_UART,
+ .data = PORTIO_UART_COM1
+ };
+ _initData.log_object = serial_i;
+}
+
+void
+portio_uart_write(uint64_t dev, const char *s, int n)
+{
+ for(int i = 0; i < n; i++) {
+ port_outb(dev, s[i]);
+ }
+}
+
+#endif
diff --git a/device/uart.c b/device/uart.c
new file mode 100644
index 0000000..6728ab1
--- /dev/null
+++ b/device/uart.c
@@ -0,0 +1,13 @@
+#include "device/uart.h"
+#include "device/portio_uart.h"
+
+void
+uart_write(objdir_t *dir, uint64_t entryi, const char *s, size_t w)
+{
+ objdir_entry_t *entry = objdir_seek(dir, entryi);
+ if(entry == NULL || entry->type != KO_DEV_UART) return;
+
+#ifdef ENABLE_PORTIO_UART
+ portio_uart_write(entry->data, s, w);
+#endif
+}