summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2025-08-10 15:46:33 -0400
committerJon Santmyer <jon@jonsantmyer.com>2025-08-10 15:46:33 -0400
commit65ba015d6c1f248d36ad01a653bc49637804b15b (patch)
treea77c3fb3ca7ecac8f65eb9638d152f1e90307d0a
downloadjove-os-65ba015d6c1f248d36ad01a653bc49637804b15b.tar.gz
jove-os-65ba015d6c1f248d36ad01a653bc49637804b15b.tar.bz2
jove-os-65ba015d6c1f248d36ad01a653bc49637804b15b.zip
working usermode objdir iteration
-rw-r--r--.gitignore12
-rw-r--r--.gitmodules3
-rw-r--r--Makefile70
-rw-r--r--apps/init/Makefile21
-rw-r--r--apps/init/main.c103
-rw-r--r--apps/init/memory.h6
-rw-r--r--apps/init/x86_64.ld10
-rw-r--r--compile_commands.json62
-rw-r--r--config.mk26
-rw-r--r--initrd/Makefile12
-rwxr-xr-xinitrd/files/bin/initbin0 -> 16656 bytes
-rw-r--r--initrd/initrd.tarbin0 -> 10240 bytes
m---------kernel0
-rw-r--r--lib/libc-headless/Makefile15
-rw-r--r--lib/libc-headless/ctype/toupper.c9
-rw-r--r--lib/libc-headless/include/ctype.h7
-rw-r--r--lib/libc-headless/include/errno.h0
-rw-r--r--lib/libc-headless/include/stdint.h319
-rw-r--r--lib/libc-headless/include/stdio.h32
-rw-r--r--lib/libc-headless/include/stdlib.h17
-rw-r--r--lib/libc-headless/include/string.h11
-rw-r--r--lib/libc-headless/include/sys/types.h6
-rw-r--r--lib/libc-headless/include/time.h4
-rw-r--r--lib/libc-headless/include/unistd.h11
-rw-r--r--lib/libc-headless/stdio/sprintf.c124
-rw-r--r--lib/libc-headless/string/memcpy.c10
-rw-r--r--lib/libc-headless/string/memset.c7
-rw-r--r--lib/libjove/Makefile18
-rw-r--r--lib/libjove/arch/x86_64/invoke-pagemap.c21
-rw-r--r--lib/libjove/include/arch/x86_64/object-pagemap.h14
-rw-r--r--lib/libjove/include/arch/x86_64/syscall.h12
-rw-r--r--lib/libjove/include/jove.h13
-rw-r--r--lib/libjove/include/object-dir.h17
-rw-r--r--lib/libjove/include/object-message.h13
-rw-r--r--lib/libjove/include/object-typed.h15
-rw-r--r--lib/libjove/include/object-untyped.h39
-rw-r--r--lib/libjove/include/object.h11
-rw-r--r--lib/libjove/include/path-fromobj.h13
-rw-r--r--lib/libjove/include/syscall.h35
-rw-r--r--lib/libjove/kprintf.c16
-rw-r--r--lib/libjove/libjove.c11
-rw-r--r--lib/libjove/object/directory.c4
-rw-r--r--lib/libjove/syscall/debug_putc.c13
-rw-r--r--lib/libjove/syscall/invoke-objdir.c39
-rw-r--r--lib/libjove/syscall/invoke-untyped.c52
-rw-r--r--lib/libjove/syscall/invoke.c14
-rw-r--r--lib/libjove/syscall/path-fromobj.c33
-rw-r--r--limine.mk9
-rw-r--r--scripts/binutils-2.41.diff77
-rw-r--r--scripts/buildtools.mk63
-rw-r--r--scripts/gcc-13.2.0.diff86
-rw-r--r--shell.nix30
-rw-r--r--sysroot/boot/initrd.tarbin0 -> 20480 bytes
-rw-r--r--sysroot/boot/limine.conf15
54 files changed, 1580 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..676fa0e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+*.a
+*.o
+*.elf
+*.hdd
+.ccls*
+tools
+ovmf*
+limine
+.cache
+sysroot/usr
+sysroot/lib
+initrd/archive
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..46609a0
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "kernel"]
+ path = kernel
+ url = https://git.jonsantmyer.com/jove-kernel
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b63fa27
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,70 @@
+include config.mk
+
+KERNEL_BIN := $(KERNELDIR)/jove.elf
+INITRD_TAR := $(SYSROOTDIR)/boot/initrd.tar
+
+TEST_HDD := $(PWD)/test.hdd
+TEST_HDD_SIZEM = 64
+TEST_HDD_DIR := $(PWD)/test_hdd
+
+all: $(KERNEL_BIN)
+
+.PHONY: clean
+clean:
+ $(MAKE) -C $(KERNELDIR) clean CONFIG=$(PWD)/config.mk
+ -rm $(STATICLIBS)
+ -rm $(APPS)
+ $(foreach dir, $(filter %/, $(wildcard $(APPSDIR)/*/)), $(MAKE) -C $(dir) clean CONFIG=$(PWD)/config.mk)
+ $(foreach dir, $(filter %/, $(wildcard $(LIBDIR)/*/)), $(MAKE) -C $(dir) clean CONFIG=$(PWD)/config.mk)
+
+.PHONY: $(KERNEL_BIN)
+$(KERNEL_BIN):
+ $(MAKE) -C $(KERNELDIR) CONFIG=$(PWD)/config.mk
+
+.PHONY: $(INITRD_TAR)
+$(INITRD_TAR): $(APPS)
+ $(MAKE) -C $(INITRDDIR) CONFIG=$(PWD)/config.mk OUT=$(INITRD_TAR)
+
+$(INITRDDIR)/files/bin/% : $(STATICLIBS) FORCE
+ $(MAKE) -C $(APPSDIR)/$(subst $(INITRDDIR)/files/bin/,,$@) CONFIG=$(PWD)/config.mk OUT=$(INITRDDIR)/files/bin
+
+$(SYSROOTDIR)/lib/%.a : $(SYSROOTDIR) FORCE
+ $(MAKE) -C $(LIBDIR)/$(subst $(SYSROOTDIR)/lib/,,$(subst .a,,$@)) CONFIG=$(PWD)/config.mk OUT=$(SYSROOTDIR)/lib
+
+.PHONY: $(SYSROOTDIR)/usr/include
+$(SYSROOTDIR)/usr/include:
+ rm -rf $(SYSROOTDIR)/usr/include
+ cp -r $(LIBDIR)/libc-headless/include $(SYSROOTDIR)/usr/include
+ cp -r $(KERNELDIR)/include/ $(SYSROOTDIR)/usr/include/kernel
+ cp -r $(LIBDIR)/libjove/include $(SYSROOTDIR)/usr/include/jove
+
+$(SYSROOTDIR): $(SYSROOTDIR)/usr/include
+
+.PHONY: test
+.ONESHELL:
+test: $(TEST_HDD) $(KERNEL_BIN) $(INITRD_TAR) $(SYSROOTDIR)
+ sudo rm -rf $(TEST_HDD_DIR)
+ mkdir -p $(TEST_HDD_DIR)
+ export LOOPBACK_DEV=$(shell sudo losetup -Pf --show $(TEST_HDD))
+ sudo partprobe $$LOOPBACK_DEV
+ sudo mkfs.fat -F 32 "$$LOOPBACK_DEV"p1
+ sudo mount "$$LOOPBACK_DEV"p1 $(TEST_HDD_DIR)
+ sudo cp -r $(SYSROOTDIR)/* $(TEST_HDD_DIR)
+ sudo cp $(KERNEL_BIN) $(TEST_HDD_DIR)/boot
+ sudo cp limine/limine.exe $(TEST_HDD_DIR)/boot
+ sudo mkdir -p $(TEST_HDD_DIR)/EFI/BOOT
+ sudo cp limine/BOOTX64.EFI $(TEST_HDD_DIR)/EFI/BOOT
+ sync
+ sudo umount $(TEST_HDD_DIR)
+ sudo losetup -d $$LOOPBACK_DEV
+ sudo rm -rf $(TEST_HDD_DIR)
+ qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -hda test.hdd -serial stdio -no-shutdown -no-reboot -s -d int -d guest_errors
+
+.PHONY: $(TEST_HDD)
+$(TEST_HDD):
+ rm -f $(TEST_HDD)
+ dd if=/dev/zero bs=1M count=0 seek=$(TEST_HDD_SIZEM) of=$(TEST_HDD)
+ parted -s $(TEST_HDD) mklabel gpt
+ parted -s $(TEST_HDD) mkpart primary 2048s 100%
+
+FORCE: ;
diff --git a/apps/init/Makefile b/apps/init/Makefile
new file mode 100644
index 0000000..642ca38
--- /dev/null
+++ b/apps/init/Makefile
@@ -0,0 +1,21 @@
+include $(CONFIG)
+
+CFILES := $(wildcard *.c)
+OFILES := $(patsubst %.c,%.o,$(CFILES))
+OFILES += $(STATICLIBS)
+
+CFLAGS := -ffreestanding -nostdlib -g
+LDFLAGS := -T $(TARGET_MACHINE).ld
+OCFLAGS := -O binary \
+ --set-section-flags .bss=alloc,load,contents
+
+all: $(OFILES)
+ $(LD) $(LDFLAGS) ${OFILES} -o init.elf
+ objcopy $(OCFLAGS) init.elf $(OUT)/init
+
+clean:
+ -rm ${OFILES}
+ -rm init.elf
+
+%.o:%.c
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/apps/init/main.c b/apps/init/main.c
new file mode 100644
index 0000000..c8dabdf
--- /dev/null
+++ b/apps/init/main.c
@@ -0,0 +1,103 @@
+#include <stdint.h>
+#include <string.h>
+#include <kernel/object.h>
+#include <jove/jove.h>
+#include <jove/object.h>
+#include <jove/syscall.h>
+#include <jove/arch/x86_64/object-pagemap.h>
+
+/**This program acts as a memory and process server.*/
+
+#define INIT_HEAP_START_BYTES 4096
+__attribute__((section(".bss.heap")))
+uint8_t init_heap[INIT_HEAP_START_BYTES];
+size_t init_heap_start = (uintptr_t)init_heap;
+
+__attribute__((noreturn))
+static void
+spin_fail(void)
+{
+ for(;;);
+}
+
+void*
+init_bumpalloc(size_t bytes)
+{
+ void *r = (void*)init_heap_start;
+ init_heap_start += bytes;
+ return r;
+}
+
+KernelObjectTyped _logObject;
+KernelObjectDirectory _untypedDirectory;
+KernelObjectDirectory _processorDirectory;
+KernelObjectPageMapping _pageMapping;
+KernelObjectDirectory _initrd;
+KernelObjectMessage _messageObject;
+
+#define POPULATE_ROOTDIR_MEMB(memb, i) \
+{ KernelObjectTyped *typed = JOVE_OBJECT_TYPED(memb); \
+ __rootdir.children[i] = typed; \
+ typed->parent = JOVE_OBJECT_TYPED(&__rootdir); \
+ typed->membi = i; \
+ if(_syscall_invoke_objdir_getmemb(&__rootdir, i, &typed->type) != 0) { \
+ jove_kprintf("Failed to populate objdir root member %i\n", i); \
+ spin_fail(); \
+ } \
+}
+
+static void
+s_populate_rootdir(init_data_t *init_data)
+{
+ __rootdir.typed.parent = NULL;
+ __rootdir.children[0] = JOVE_OBJECT_TYPED(&__rootdir);
+
+ POPULATE_ROOTDIR_MEMB(&_logObject, init_data->log_object);
+ POPULATE_ROOTDIR_MEMB(&_untypedDirectory, init_data->untyped_data_dir);
+ POPULATE_ROOTDIR_MEMB(&_processorDirectory, init_data->processor_dir);
+ POPULATE_ROOTDIR_MEMB(&_pageMapping, init_data->pm_object);
+ POPULATE_ROOTDIR_MEMB(&_initrd, init_data->initrd_dir);
+ POPULATE_ROOTDIR_MEMB(&_messageObject, init_data->message_object);
+
+ //Populate untyped table
+ for(int i = 1; i < 256; i++) {
+ KernelObjectUntyped untyped;
+ untyped.typed.parent = &_untypedDirectory;
+ untyped.typed.membi = i;
+ if(_syscall_invoke_objdir_getmemb(&_untypedDirectory, i, &untyped.typed.type) != 0) {
+ jove_kprintf("Failed to get member %i of untyped directory\n", i);
+ spin_fail();
+ }
+ if(untyped.typed.type != KO_MEMORY_UNTYPED) continue;
+ _untypedDirectory.children[i] = init_bumpalloc(sizeof(KernelObjectUntyped));
+ memcpy(_untypedDirectory.children[i], &untyped, sizeof(KernelObjectUntyped));
+
+ _syscall_invoke_untyped_size(&untyped, &untyped.bytes);
+ _syscall_invoke_untyped_alignment(&untyped, &untyped.alignment);
+
+ jove_kprintf("Untyped %i size %X align %X\n", i, untyped.bytes, untyped.alignment);
+ }
+}
+
+void
+main(init_data_t *init_data)
+{
+ libjove_init(
+ (uintmax_t)init_data->message_object,
+ (void*)init_data->message_object_address);
+ jove_kprintf("Hello, Userland!\n");
+
+ s_populate_rootdir(init_data);
+
+ for(;;);
+}
+
+__attribute__((section(".text.start")))
+__attribute__((naked))
+void
+_start(void)
+{
+ __asm__ volatile("\
+ popq %%rdi; \
+ jmp main"::);
+}
diff --git a/apps/init/memory.h b/apps/init/memory.h
new file mode 100644
index 0000000..61d16d6
--- /dev/null
+++ b/apps/init/memory.h
@@ -0,0 +1,6 @@
+#ifndef _INIT_MEMORY_H
+#define _INIT_MEMORY_H 1
+
+
+
+#endif
diff --git a/apps/init/x86_64.ld b/apps/init/x86_64.ld
new file mode 100644
index 0000000..45b08f5
--- /dev/null
+++ b/apps/init/x86_64.ld
@@ -0,0 +1,10 @@
+OUTPUT_ARCH(i386:x86-64)
+
+PAGESIZE = CONSTANT(MAXPAGESIZE);
+
+SECTIONS
+{
+ . = 0x1000;
+ .text BLOCK(PAGESIZE) : ALIGN(PAGESIZE) { *(.text.start) *(.text) *(.rodata) }
+ .data BLOCK(PAGESIZE) : ALIGN(PAGESIZE) { *(.data) *(.bss) }
+}
diff --git a/compile_commands.json b/compile_commands.json
new file mode 100644
index 0000000..83764f8
--- /dev/null
+++ b/compile_commands.json
@@ -0,0 +1,62 @@
+[
+ {
+ "directory": "/home/jon/prg/jove/kernel",
+ "arguments": [
+ "/home/jon/prg/jove/tools/bin/x86_64-jove-gcc",
+ "-ffreestanding",
+ "-mno-sse",
+ "-nostdlib",
+ "-fno-pie",
+ "-fno-pic",
+ "-g",
+ "-D__x86_64__",
+ "-D__limine__",
+ "-Iinclude",
+ "-I.",
+ "-mno-red-zone",
+ "-mcmodel=kernel",
+ "-mfsgsbase",
+ "-DKERNEL_STACKBYTES=4096",
+ "-DENABLE_PORTIO_UART",
+ "-DENABLE_UART",
+ "-DENABLE_INITRD",
+ "-DDBG_MEM",
+ "-c",
+ "main.c",
+ "-o",
+ "main.o"
+ ],
+ "file": "main.c"
+ },
+ {
+ "directory": "/home/jon/prg/jove/apps/init/",
+ "arguments": [
+ "/home/jon/prg/jove/tools/bin/x86_64-jove-gcc",
+ "-ffreestanding",
+ "-mno-sse",
+ "-nostdlib",
+ "-fno-pie",
+ "-fno-pic",
+ "-g",
+ "-I/home/jon/prg/jove/sysroot/usr/include",
+ "-c",
+ "main.c",
+ "-o",
+ "main.o"
+ ],
+ "file": "main.c"
+ },
+ {
+ "directory": "/home/jon/prg/jove/lib/libjove/",
+ "arguments": [
+ "/home/jon/prg/jove/tools/bin/x86_64-jove-gcc",
+ "-ffreestanding",
+ "-mno-sse",
+ "-nostdlib",
+ "-g",
+ "-I/home/jon/prg/jove/sysroot/usr/include",
+ "-Iinclude"
+ ],
+ "file": "libjove.c"
+ }
+]
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..1659c3a
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,26 @@
+TOOLSDIR := $(PWD)/tools
+KERNELDIR := $(PWD)/kernel
+SYSROOTDIR := $(PWD)/sysroot
+APPSDIR := $(PWD)/apps
+INITRDDIR := $(PWD)/initrd
+LIBDIR := $(PWD)/lib
+
+LIMINE_VERSION := 8.x
+LIMINE_ORIGIN := https://github.com/limine-bootloader/limine.git
+LIMINE_DIR := $(PWD)/limine
+LIMINE_GETCMD := git clone $(LIMINE_ORIGIN) --branch=v$(LIMINE_VERSION)-binary --depth 1 $(LIMINE_DIR)
+
+TARGET_MACHINE = x86_64
+TARGET_OS = jove
+TARGET_TRIPLET = $(TARGET_MACHINE)-$(TARGET_OS)
+TARGET_BOOTLOADER = limine
+
+APPS := $(INITRDDIR)/files/bin/init
+
+STATICLIBS := $(SYSROOTDIR)/lib/libjove.a \
+ $(SYSROOTDIR)/lib/libc-headless.a
+
+CC := $(TOOLSDIR)/bin/$(TARGET_TRIPLET)-gcc
+LD := $(TOOLSDIR)/bin/$(TARGET_TRIPLET)-ld
+AS := $(TOOLSDIR)/bin/$(TARGET_TRIPLET)-as
+AR := $(TOOLSDIR)/bin/$(TARGET_TRIPLET)-ar
diff --git a/initrd/Makefile b/initrd/Makefile
new file mode 100644
index 0000000..bd4956d
--- /dev/null
+++ b/initrd/Makefile
@@ -0,0 +1,12 @@
+include $(CONFIG)
+
+FILESDIR := files
+ARCHIVEDIR := archive
+
+all: $(ARCHIVEDIR)
+ tar -cf $(OUT) -C $(ARCHIVEDIR) .
+
+.PHONY: $(ARCHIVEDIR)
+$(ARCHIVEDIR):
+ rm -rf $(ARCHIVEDIR)
+ cp -r $(FILESDIR)/ $(ARCHIVEDIR)/
diff --git a/initrd/files/bin/init b/initrd/files/bin/init
new file mode 100755
index 0000000..6fa149d
--- /dev/null
+++ b/initrd/files/bin/init
Binary files differ
diff --git a/initrd/initrd.tar b/initrd/initrd.tar
new file mode 100644
index 0000000..c684cd9
--- /dev/null
+++ b/initrd/initrd.tar
Binary files differ
diff --git a/kernel b/kernel
new file mode 160000
+Subproject c4f8ef91f18d854a4ede7a94e95b2eab898d696
diff --git a/lib/libc-headless/Makefile b/lib/libc-headless/Makefile
new file mode 100644
index 0000000..59de6c8
--- /dev/null
+++ b/lib/libc-headless/Makefile
@@ -0,0 +1,15 @@
+include $(CONFIG)
+
+CDIRS := stdio ctype string
+
+CFILES += $(foreach dir,$(CDIRS),$(wildcard $(dir)/*.c))
+
+OFILES := $(patsubst %.c,%.o,$(CFILES))
+
+CFLAGS := -ffreestanding -nostdlib
+
+all: ${OFILES}
+ ar rcs $(OUT)/libc-headless.a $(OFILES)
+
+%.o:%.c
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/lib/libc-headless/ctype/toupper.c b/lib/libc-headless/ctype/toupper.c
new file mode 100644
index 0000000..fe1e1e2
--- /dev/null
+++ b/lib/libc-headless/ctype/toupper.c
@@ -0,0 +1,9 @@
+#include <ctype.h>
+
+/* TODO: Faster toupper */
+int
+toupper(int c)
+{
+ if(c >= 'a' && c <= 'z') c += 'A' - 'a';
+ return c;
+}
diff --git a/lib/libc-headless/include/ctype.h b/lib/libc-headless/include/ctype.h
new file mode 100644
index 0000000..9dfcc3b
--- /dev/null
+++ b/lib/libc-headless/include/ctype.h
@@ -0,0 +1,7 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H 1
+
+int toupper(int c);
+int tolower(int c);
+
+#endif
diff --git a/lib/libc-headless/include/errno.h b/lib/libc-headless/include/errno.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libc-headless/include/errno.h
diff --git a/lib/libc-headless/include/stdint.h b/lib/libc-headless/include/stdint.h
new file mode 100644
index 0000000..165a201
--- /dev/null
+++ b/lib/libc-headless/include/stdint.h
@@ -0,0 +1,319 @@
+/* Copyright (C) 1997-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/*
+ * ISO C99: 7.18 Integer types <stdint.h>
+ */
+
+#ifndef _STDINT_H
+#define _STDINT_H 1
+
+#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
+#include <bits/libc-header-start.h>
+#include <bits/types.h>
+#include <bits/wchar.h>
+#include <bits/wordsize.h>
+
+/* Exact integral types. */
+
+/* Signed. */
+#include <bits/stdint-intn.h>
+
+/* Unsigned. */
+#include <bits/stdint-uintn.h>
+
+
+/* Small types. */
+
+/* Signed. */
+typedef __int_least8_t int_least8_t;
+typedef __int_least16_t int_least16_t;
+typedef __int_least32_t int_least32_t;
+typedef __int_least64_t int_least64_t;
+
+/* Unsigned. */
+typedef __uint_least8_t uint_least8_t;
+typedef __uint_least16_t uint_least16_t;
+typedef __uint_least32_t uint_least32_t;
+typedef __uint_least64_t uint_least64_t;
+
+
+/* Fast types. */
+
+/* Signed. */
+typedef signed char int_fast8_t;
+#if __WORDSIZE == 64
+typedef long int int_fast16_t;
+typedef long int int_fast32_t;
+typedef long int int_fast64_t;
+#else
+typedef int int_fast16_t;
+typedef int int_fast32_t;
+__extension__
+typedef long long int int_fast64_t;
+#endif
+
+/* Unsigned. */
+typedef unsigned char uint_fast8_t;
+#if __WORDSIZE == 64
+typedef unsigned long int uint_fast16_t;
+typedef unsigned long int uint_fast32_t;
+typedef unsigned long int uint_fast64_t;
+#else
+typedef unsigned int uint_fast16_t;
+typedef unsigned int uint_fast32_t;
+__extension__
+typedef unsigned long long int uint_fast64_t;
+#endif
+
+
+/* Types for `void *' pointers. */
+#if __WORDSIZE == 64
+# ifndef __intptr_t_defined
+typedef long int intptr_t;
+# define __intptr_t_defined
+# endif
+typedef unsigned long int uintptr_t;
+#else
+# ifndef __intptr_t_defined
+typedef int intptr_t;
+# define __intptr_t_defined
+# endif
+typedef unsigned int uintptr_t;
+#endif
+
+
+/* Largest integral types. */
+typedef __intmax_t intmax_t;
+typedef __uintmax_t uintmax_t;
+
+
+# if __WORDSIZE == 64
+# define __INT64_C(c) c ## L
+# define __UINT64_C(c) c ## UL
+# else
+# define __INT64_C(c) c ## LL
+# define __UINT64_C(c) c ## ULL
+# endif
+
+/* Limits of integral types. */
+
+/* Minimum of signed integral types. */
+# define INT8_MIN (-128)
+# define INT16_MIN (-32767-1)
+# define INT32_MIN (-2147483647-1)
+# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types. */
+# define INT8_MAX (127)
+# define INT16_MAX (32767)
+# define INT32_MAX (2147483647)
+# define INT64_MAX (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types. */
+# define UINT8_MAX (255)
+# define UINT16_MAX (65535)
+# define UINT32_MAX (4294967295U)
+# define UINT64_MAX (__UINT64_C(18446744073709551615))
+
+
+/* Minimum of signed integral types having a minimum size. */
+# define INT_LEAST8_MIN (-128)
+# define INT_LEAST16_MIN (-32767-1)
+# define INT_LEAST32_MIN (-2147483647-1)
+# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types having a minimum size. */
+# define INT_LEAST8_MAX (127)
+# define INT_LEAST16_MAX (32767)
+# define INT_LEAST32_MAX (2147483647)
+# define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types having a minimum size. */
+# define UINT_LEAST8_MAX (255)
+# define UINT_LEAST16_MAX (65535)
+# define UINT_LEAST32_MAX (4294967295U)
+# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
+
+
+/* Minimum of fast signed integral types having a minimum size. */
+# define INT_FAST8_MIN (-128)
+# if __WORDSIZE == 64
+# define INT_FAST16_MIN (-9223372036854775807L-1)
+# define INT_FAST32_MIN (-9223372036854775807L-1)
+# else
+# define INT_FAST16_MIN (-2147483647-1)
+# define INT_FAST32_MIN (-2147483647-1)
+# endif
+# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1)
+/* Maximum of fast signed integral types having a minimum size. */
+# define INT_FAST8_MAX (127)
+# if __WORDSIZE == 64
+# define INT_FAST16_MAX (9223372036854775807L)
+# define INT_FAST32_MAX (9223372036854775807L)
+# else
+# define INT_FAST16_MAX (2147483647)
+# define INT_FAST32_MAX (2147483647)
+# endif
+# define INT_FAST64_MAX (__INT64_C(9223372036854775807))
+
+/* Maximum of fast unsigned integral types having a minimum size. */
+# define UINT_FAST8_MAX (255)
+# if __WORDSIZE == 64
+# define UINT_FAST16_MAX (18446744073709551615UL)
+# define UINT_FAST32_MAX (18446744073709551615UL)
+# else
+# define UINT_FAST16_MAX (4294967295U)
+# define UINT_FAST32_MAX (4294967295U)
+# endif
+# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
+
+
+/* Values to test for integral types holding `void *' pointer. */
+# if __WORDSIZE == 64
+# define INTPTR_MIN (-9223372036854775807L-1)
+# define INTPTR_MAX (9223372036854775807L)
+# define UINTPTR_MAX (18446744073709551615UL)
+# else
+# define INTPTR_MIN (-2147483647-1)
+# define INTPTR_MAX (2147483647)
+# define UINTPTR_MAX (4294967295U)
+# endif
+
+
+/* Minimum for largest signed integral type. */
+# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1)
+/* Maximum for largest signed integral type. */
+# define INTMAX_MAX (__INT64_C(9223372036854775807))
+
+/* Maximum for largest unsigned integral type. */
+# define UINTMAX_MAX (__UINT64_C(18446744073709551615))
+
+
+/* Limits of other integer types. */
+
+/* Limits of `ptrdiff_t' type. */
+# if __WORDSIZE == 64
+# define PTRDIFF_MIN (-9223372036854775807L-1)
+# define PTRDIFF_MAX (9223372036854775807L)
+# else
+# if __WORDSIZE32_PTRDIFF_LONG
+# define PTRDIFF_MIN (-2147483647L-1)
+# define PTRDIFF_MAX (2147483647L)
+# else
+# define PTRDIFF_MIN (-2147483647-1)
+# define PTRDIFF_MAX (2147483647)
+# endif
+# endif
+
+/* Limits of `sig_atomic_t'. */
+# define SIG_ATOMIC_MIN (-2147483647-1)
+# define SIG_ATOMIC_MAX (2147483647)
+
+/* Limit of `size_t' type. */
+# if __WORDSIZE == 64
+# define SIZE_MAX (18446744073709551615UL)
+# else
+# if __WORDSIZE32_SIZE_ULONG
+# define SIZE_MAX (4294967295UL)
+# else
+# define SIZE_MAX (4294967295U)
+# endif
+# endif
+
+/* Limits of `wchar_t'. */
+# ifndef WCHAR_MIN
+/* These constants might also be defined in <wchar.h>. */
+# define WCHAR_MIN __WCHAR_MIN
+# define WCHAR_MAX __WCHAR_MAX
+# endif
+
+/* Limits of `wint_t'. */
+# define WINT_MIN (0u)
+# define WINT_MAX (4294967295u)
+
+/* Signed. */
+# define INT8_C(c) c
+# define INT16_C(c) c
+# define INT32_C(c) c
+# if __WORDSIZE == 64
+# define INT64_C(c) c ## L
+# else
+# define INT64_C(c) c ## LL
+# endif
+
+/* Unsigned. */
+# define UINT8_C(c) c
+# define UINT16_C(c) c
+# define UINT32_C(c) c ## U
+# if __WORDSIZE == 64
+# define UINT64_C(c) c ## UL
+# else
+# define UINT64_C(c) c ## ULL
+# endif
+
+/* Maximal type. */
+# if __WORDSIZE == 64
+# define INTMAX_C(c) c ## L
+# define UINTMAX_C(c) c ## UL
+# else
+# define INTMAX_C(c) c ## LL
+# define UINTMAX_C(c) c ## ULL
+# endif
+
+#if __GLIBC_USE (IEC_60559_BFP_EXT_C2X)
+
+# define INT8_WIDTH 8
+# define UINT8_WIDTH 8
+# define INT16_WIDTH 16
+# define UINT16_WIDTH 16
+# define INT32_WIDTH 32
+# define UINT32_WIDTH 32
+# define INT64_WIDTH 64
+# define UINT64_WIDTH 64
+
+# define INT_LEAST8_WIDTH 8
+# define UINT_LEAST8_WIDTH 8
+# define INT_LEAST16_WIDTH 16
+# define UINT_LEAST16_WIDTH 16
+# define INT_LEAST32_WIDTH 32
+# define UINT_LEAST32_WIDTH 32
+# define INT_LEAST64_WIDTH 64
+# define UINT_LEAST64_WIDTH 64
+
+# define INT_FAST8_WIDTH 8
+# define UINT_FAST8_WIDTH 8
+# define INT_FAST16_WIDTH __WORDSIZE
+# define UINT_FAST16_WIDTH __WORDSIZE
+# define INT_FAST32_WIDTH __WORDSIZE
+# define UINT_FAST32_WIDTH __WORDSIZE
+# define INT_FAST64_WIDTH 64
+# define UINT_FAST64_WIDTH 64
+
+# define INTPTR_WIDTH __WORDSIZE
+# define UINTPTR_WIDTH __WORDSIZE
+
+# define INTMAX_WIDTH 64
+# define UINTMAX_WIDTH 64
+
+# define PTRDIFF_WIDTH __WORDSIZE
+# define SIG_ATOMIC_WIDTH 32
+# define SIZE_WIDTH __WORDSIZE
+# define WCHAR_WIDTH 32
+# define WINT_WIDTH 32
+
+#endif
+
+#endif /* stdint.h */
diff --git a/lib/libc-headless/include/stdio.h b/lib/libc-headless/include/stdio.h
new file mode 100644
index 0000000..cd29004
--- /dev/null
+++ b/lib/libc-headless/include/stdio.h
@@ -0,0 +1,32 @@
+#ifndef _STDIO_H
+#define _STDIO_H 1
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#define SEEK_SET 0
+typedef struct { int unused; } FILE;
+
+extern FILE *stderr;
+#define stderr stderr
+
+int fclose(FILE *file);
+int fflush(FILE *file);
+FILE *fopen(const char *path, const char *flags);
+
+size_t fread(void *buf, size_t size, size_t nmemb, FILE* file);
+int fseek(FILE *file, long offset, int whence);
+long ftell(FILE *file);
+size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *file);
+void setbuf(FILE *file, char *buf);
+
+int fprintf(FILE *file, const char *fmt, ...);
+int vfprintf(FILE *file, const char *fmt, va_list ap);
+
+int sprintf(char *restrict str, const char *restrict format, ...);
+int vsprintf(char *restrict str, const char *restrict format, va_list ap);
+
+int snprintf(char *restrict str, size_t size, const char *restrict format, ...);
+int vsnprintf(char *restrict str, size_t size, const char *restrict format, va_list ap);
+
+#endif
diff --git a/lib/libc-headless/include/stdlib.h b/lib/libc-headless/include/stdlib.h
new file mode 100644
index 0000000..f29cce7
--- /dev/null
+++ b/lib/libc-headless/include/stdlib.h
@@ -0,0 +1,17 @@
+#ifndef _STDLIB_H
+#define _STDLIB_H 1
+
+#include <stddef.h>
+
+__attribute__((noreturn)) void abort(void);
+int atexit(void (*callback)(void));
+
+int atoi(const char*);
+
+void free(void *ptr);
+void *malloc(size_t size);
+void *calloc(size_t nmemb, size_t size);
+
+char *getenv(const char *key);
+
+#endif
diff --git a/lib/libc-headless/include/string.h b/lib/libc-headless/include/string.h
new file mode 100644
index 0000000..d55bc37
--- /dev/null
+++ b/lib/libc-headless/include/string.h
@@ -0,0 +1,11 @@
+#ifndef _STRING_H
+#define _STRING_H 1
+
+#include <stddef.h>
+
+void *memcpy(void *dest, const void *src, size_t size);
+void *memset(void *dest, int byte, size_t size);
+char *strcpy(char *dest, const char *src);
+size_t strlen(const char *str);
+
+#endif
diff --git a/lib/libc-headless/include/sys/types.h b/lib/libc-headless/include/sys/types.h
new file mode 100644
index 0000000..058c38a
--- /dev/null
+++ b/lib/libc-headless/include/sys/types.h
@@ -0,0 +1,6 @@
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H 1
+
+typedef int pid_t;
+
+#endif
diff --git a/lib/libc-headless/include/time.h b/lib/libc-headless/include/time.h
new file mode 100644
index 0000000..c73ee97
--- /dev/null
+++ b/lib/libc-headless/include/time.h
@@ -0,0 +1,4 @@
+#ifndef _TIME_H
+#define _TIME_H 1
+
+#endif
diff --git a/lib/libc-headless/include/unistd.h b/lib/libc-headless/include/unistd.h
new file mode 100644
index 0000000..4e14be9
--- /dev/null
+++ b/lib/libc-headless/include/unistd.h
@@ -0,0 +1,11 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H 1
+
+#include <sys/types.h>
+
+int execv(const char *pathname, char *const argv[]);
+int execve(const char *pathname, char *const argv[], char *const envp[]);
+int execvp(const char *pathname, char *const argv[]);
+pid_t fork(void);
+
+#endif
diff --git a/lib/libc-headless/stdio/sprintf.c b/lib/libc-headless/stdio/sprintf.c
new file mode 100644
index 0000000..2881bd5
--- /dev/null
+++ b/lib/libc-headless/stdio/sprintf.c
@@ -0,0 +1,124 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#define VSNPRINTF_PUTC(c) if(size > written) str[written++] = c; else written++
+
+int
+vsnprintf(char *restrict str, size_t size, const char *restrict format, va_list ap)
+{
+ int written = 0;
+ for(int fmti = 0; format[fmti] != 0; fmti++) {
+ char fmtc = format[fmti];
+ if(fmtc != '%') {
+ VSNPRINTF_PUTC(fmtc);
+ continue;
+ }
+
+ /* Flags */
+ bool alternate = false;
+ bool zeropad = false;
+ bool leftadj = false;
+ bool signspace = false;
+ bool showplus = false;
+ fmtc = format[++fmti];
+
+ switch(fmtc) {
+ case '#': alternate = true; fmti++; break;
+ case '0': zeropad = true; fmti++; break;
+ case '-': leftadj = true; fmti++; break;
+ case ' ': signspace = true; fmti++; break;
+ case '+': showplus = true; fmti++; break;
+ default: break;
+ }
+
+ /* Field width. */
+ fmtc = format[fmti];
+ //TODO: Implement field width
+
+ /* Precision. */
+ fmtc = format[fmti];
+ //TODO: Implement precision
+
+ /* Length modifier */
+ fmtc = format[fmti];
+ //TODO: Implement length modifier.
+
+ /* Conversion specifier. */
+ bool is_signed = true;
+ bool is_caps = false;
+ int radix = 10;
+ fmtc = format[fmti];
+ switch(fmtc)
+ {
+ case 'X':
+ is_caps = true;
+ case 'x':
+ radix = 16;
+ case 'u':
+ is_signed = false;
+ case 'd':
+ case 'i':
+ goto conversion_int;
+ case 'p':
+ alternate = true;
+ radix = 16;
+ is_signed = false;
+ is_caps = true;
+ goto conversion_int;
+ case '%':
+ VSNPRINTF_PUTC('%');
+ break;
+ }
+ continue;
+
+conversion_int:
+ {
+ uintmax_t value = va_arg(ap, uintmax_t);
+ bool negative = is_signed && (intmax_t)value < 0;
+ if(negative) value = (uintmax_t)(-(intmax_t)value);
+ size_t numc = 0;
+
+ /*Count the number of characters to put in the buffer to represent
+ * the value in ASCII.*/
+ for(uintmax_t v = value; v != 0; v /= radix, numc++);
+ if(numc == 0) numc++;
+
+ /* Reserve space for alternate repersentation.*/
+ if(showplus && !negative) { VSNPRINTF_PUTC('+'); }
+ if(negative) { VSNPRINTF_PUTC('-'); }
+ if(signspace && !negative) { VSNPRINTF_PUTC(' '); }
+ if(alternate) {
+ VSNPRINTF_PUTC('0');
+ if(radix == 16) {
+ VSNPRINTF_PUTC('x');
+ }
+ if(alternate && radix == 2) {
+ VSNPRINTF_PUTC('b');
+ }
+ }
+
+ /* Try to put characters into the buffer*/
+ if(value == 0) {
+ VSNPRINTF_PUTC('0');
+ }
+ else {
+ for(uintmax_t v = value, i = numc - 1; v != 0; v /= radix, i--) {
+ if(written + i >= size) continue;
+ int digit = v % radix;
+ char c = digit > 10 ? (digit + 'a' - 10) : (digit + '0');
+ if(is_caps) c = toupper(c);
+ str[written + i] = c;
+ }
+ written += numc;
+ }
+ continue;
+ }
+ }
+ VSNPRINTF_PUTC(0);
+ return written - 1;
+}
+
+
diff --git a/lib/libc-headless/string/memcpy.c b/lib/libc-headless/string/memcpy.c
new file mode 100644
index 0000000..f71444d
--- /dev/null
+++ b/lib/libc-headless/string/memcpy.c
@@ -0,0 +1,10 @@
+#include <stddef.h>
+
+void*
+memcpy(void *dest, const void *src, size_t n)
+{
+ const unsigned char *s = src;
+ for(unsigned char *d = dest; n; n--)
+ *(d++) = *(s++);
+ return dest;
+}
diff --git a/lib/libc-headless/string/memset.c b/lib/libc-headless/string/memset.c
new file mode 100644
index 0000000..f79a4b4
--- /dev/null
+++ b/lib/libc-headless/string/memset.c
@@ -0,0 +1,7 @@
+#include <stddef.h>
+
+void
+memset(void *s, int c, size_t n)
+{
+ for(unsigned char *sb = s; n; n--) *(sb++) = c;
+}
diff --git a/lib/libjove/Makefile b/lib/libjove/Makefile
new file mode 100644
index 0000000..cc5f347
--- /dev/null
+++ b/lib/libjove/Makefile
@@ -0,0 +1,18 @@
+include $(CONFIG)
+
+CDIRS := syscall object arch/$(TARGET_MACHINE)
+CFILES := $(wildcard *.c)
+CFILES += $(foreach dir,$(CDIRS),$(wildcard $(dir)/*.c))
+
+OFILES := $(patsubst %.c,%.o,$(CFILES))
+
+CFLAGS := -ffreestanding -nostdlib -Iinclude -g
+
+all: ${OFILES}
+ ar rcs $(OUT)/libjove.a $(OFILES)
+
+clean:
+ -rm $(OFILES)
+
+%.o:%.c
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/lib/libjove/arch/x86_64/invoke-pagemap.c b/lib/libjove/arch/x86_64/invoke-pagemap.c
new file mode 100644
index 0000000..8357904
--- /dev/null
+++ b/lib/libjove/arch/x86_64/invoke-pagemap.c
@@ -0,0 +1,21 @@
+#include <arch/x86_64/object-pagemap.h>
+#include <kernel/syscall.h>
+#include <kernel/arch/x86_64/syscall.h>
+#include <object.h>
+#include <path-fromobj.h>
+#include <syscall.h>
+#include <jove/jove.h>
+
+int
+_syscall_invoke_mapping_get(KernelObjectPageMapping *mapping, uint16_t pmli, KernelObjectPageMapping *dest)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, mapping);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_MAPPING_GET, uint8_t);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, pmli, uint16_t);
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dest);
+
+ return _syscall_invoke();
+}
diff --git a/lib/libjove/include/arch/x86_64/object-pagemap.h b/lib/libjove/include/arch/x86_64/object-pagemap.h
new file mode 100644
index 0000000..55b0570
--- /dev/null
+++ b/lib/libjove/include/arch/x86_64/object-pagemap.h
@@ -0,0 +1,14 @@
+#ifndef _LIBJOVE_ARCH_x86_64_OBJECT_PAGEMAP_H
+#define _LIBJOVE_ARCH_x86_64_OBJECT_PAGEMAP_H 1
+
+#include <jove/object-typed.h>
+
+typedef struct KernelObjectPageMapping
+{
+ KernelObjectTyped typed;
+ uint8_t level;
+} KernelObjectPageMapping;
+
+
+
+#endif
diff --git a/lib/libjove/include/arch/x86_64/syscall.h b/lib/libjove/include/arch/x86_64/syscall.h
new file mode 100644
index 0000000..1d7df53
--- /dev/null
+++ b/lib/libjove/include/arch/x86_64/syscall.h
@@ -0,0 +1,12 @@
+#ifndef _LIBJOVE_ARCH_x86_64_SYSCALL_H
+#define _LIBJOVE_ARCH_x86_64_SYSCALL_H 1
+
+#include <stdint.h>
+
+#include <kernel/object.h>
+#include <jove/object-path.h>
+
+int _syscall_invoke_mapping_get(KernelObjectPath path, uint16_t pmli, KernelObjectPath destPath);
+
+
+#endif
diff --git a/lib/libjove/include/jove.h b/lib/libjove/include/jove.h
new file mode 100644
index 0000000..2efef3e
--- /dev/null
+++ b/lib/libjove/include/jove.h
@@ -0,0 +1,13 @@
+#ifndef _LIBJOVE_JOVE_H
+#define _LIBJOVE_JOVE_H 1
+
+#include <stdint.h>
+
+extern uintmax_t _syscall_message_box;
+extern void *_syscall_message_ptr;
+
+void libjove_init(uintmax_t box, void *boxptr);
+
+void jove_kprintf(const char *restrict fmt, ...);
+
+#endif
diff --git a/lib/libjove/include/object-dir.h b/lib/libjove/include/object-dir.h
new file mode 100644
index 0000000..f258089
--- /dev/null
+++ b/lib/libjove/include/object-dir.h
@@ -0,0 +1,17 @@
+#ifndef _LIBJOVE_OBJDIR_H
+#define _LIBJOVE_OBJDIR_H 1
+
+#include <stdint.h>
+#include <stddef.h>
+#include <kernel/object.h>
+
+#include <jove/object-typed.h>
+
+/**@STRUCT Represents a kobjdir.*/
+typedef struct _KernelObjectDirectory {
+ KernelObjectTyped typed;
+ KernelObjectTyped *children[256];
+} KernelObjectDirectory;
+extern KernelObjectDirectory __rootdir;
+
+#endif
diff --git a/lib/libjove/include/object-message.h b/lib/libjove/include/object-message.h
new file mode 100644
index 0000000..a4b7d35
--- /dev/null
+++ b/lib/libjove/include/object-message.h
@@ -0,0 +1,13 @@
+#ifndef _LIBJOVE_OBJECT_MESSAGE_H
+#define _LIBJOVE_OBJECT_MESSAGE_H 1
+
+#include <jove/object-typed.h>
+
+typedef struct _KernelObjectMessage
+{
+ KernelObjectTyped typed;
+ uint16_t pages;
+ void *data;
+} KernelObjectMessage;
+
+#endif
diff --git a/lib/libjove/include/object-typed.h b/lib/libjove/include/object-typed.h
new file mode 100644
index 0000000..750cf08
--- /dev/null
+++ b/lib/libjove/include/object-typed.h
@@ -0,0 +1,15 @@
+#ifndef _LIBJOVE_OBJPATH_H
+#define _LIBJOVE_OBJPATH_H 1
+
+#include <stddef.h>
+#include <stdint.h>
+#include <kernel/object.h>
+
+typedef struct KernelObjectTyped
+{
+ void *parent;
+ obj_type_t type;
+ uint8_t membi;
+} KernelObjectTyped;
+
+#endif
diff --git a/lib/libjove/include/object-untyped.h b/lib/libjove/include/object-untyped.h
new file mode 100644
index 0000000..ea1185d
--- /dev/null
+++ b/lib/libjove/include/object-untyped.h
@@ -0,0 +1,39 @@
+#ifndef _LIBJOVE_OBJECT_UNTYPED_H
+#define _LIBJOVE_OBJECT_UNTYPED_H 1
+
+#include <jove/object-typed.h>
+
+/**@STRUCT Represents a KO_MEMOY_UNTYPED*/
+typedef struct KernelObjectUntyped
+{
+ KernelObjectTyped typed;
+ size_t bytes, alignment;
+} KernelObjectUntyped;
+
+/**@FUNC Gets the size of the given untyped memory block.
+ * @PARAM untyped block of memory to get size of.
+ * @PARAM bytes address to put size variable into.
+ * @RETURN error code. 0 on success.*/
+int jove_untyped_size(KernelObjectUntyped *untyped, size_t *bytes);
+
+/**@FUNC Splits an untyped block of memory into a given size and the remainder.
+ * @PARAM untyped block of memory to split.
+ * @PARAM bytes number of bytes to split for.
+ * @PARAM dest destination slot to place the new block.
+ * @RETURN error code. 0 on success.*/
+int jove_untyped_split(KernelObjectUntyped *untyped, size_t bytes, KernelObjectUntyped *dest);
+
+/**@FUNC Merges two untyped memory blocks into a single memory block.
+ * The two blocks are expected to be adjacent.
+ * If successful, b is merged _into_ a and becomes empty.
+ * @PARAM a first block.
+ * @PARAM b second block.
+ * @RETURN error code. 0 on success.*/
+int jove_untyped_merge(KernelObjectUntyped *a, KernelObjectUntyped *b);
+
+/**@FUNC Gets the page alignment of the given untyped memory block.
+ * @PARAM untyped block of memory to get alignment of.
+ * @PARAM align pointer to returned value.
+ * @RETURN error code. 0 on success.*/
+int jove_untyped_alignment(KernelObjectUntyped *untyped, size_t *align);
+#endif
diff --git a/lib/libjove/include/object.h b/lib/libjove/include/object.h
new file mode 100644
index 0000000..5b0cc82
--- /dev/null
+++ b/lib/libjove/include/object.h
@@ -0,0 +1,11 @@
+#ifndef _LIBJOVE_OBJECT_H
+#define _LIBJOVE_OBJECT_H 1
+
+#include <jove/object-typed.h>
+#include <jove/object-dir.h>
+#include <jove/object-untyped.h>
+#include <jove/object-message.h>
+
+#define JOVE_OBJECT_TYPED(o) (KernelObjectTyped*)o
+
+#endif
diff --git a/lib/libjove/include/path-fromobj.h b/lib/libjove/include/path-fromobj.h
new file mode 100644
index 0000000..252be29
--- /dev/null
+++ b/lib/libjove/include/path-fromobj.h
@@ -0,0 +1,13 @@
+#ifndef _LIBJOVE_PATH_FROMOBJ_H
+#define _LIBJOVE_PATH_FROMOBJ_H 1
+
+#include <jove/object-typed.h>
+#include <kernel/object.h>
+
+int path_fromobj_s(KernelObjectTyped *obj, uint8_t *buffer, int size);
+inline int path_fromobj(KernelObjectTyped *obj, uint8_t *buffer)
+{ return path_fromobj_s(obj, buffer, -1); }
+
+int path_tobuf(KernelObjectTyped *obj, uint8_t *buffer, size_t at, size_t bufferw);
+
+#endif
diff --git a/lib/libjove/include/syscall.h b/lib/libjove/include/syscall.h
new file mode 100644
index 0000000..432be85
--- /dev/null
+++ b/lib/libjove/include/syscall.h
@@ -0,0 +1,35 @@
+#ifndef _LIBJOVE_SYSCALL_H
+#define _LIBJOVE_SYSCALL_H 1
+
+#include <stdint.h>
+
+#include <kernel/object.h>
+#include <jove/object.h>
+
+#define SYSCALL_PAYLOAD_PUTL(buf, at, v, type) \
+ if(at + sizeof(type) > KO_MESSAGE_BYTES) return -1; \
+ *((type*)(&buf[at])) = v; \
+ at += sizeof(type)
+
+#define SYSCALL_PAYLOAD_SAVEPTR(buf, at, type, val) \
+ if(at + sizeof(type) >= KO_MESSAGE_BYTES) return -1; \
+ val = (type*)(&buf[at]); \
+ at += sizeof(type)
+
+#define SYSCALL_PAYLOAD_PUTOBJ(buf, at, obj) \
+ at = path_tobuf(JOVE_OBJECT_TYPED(obj), buf, at, KO_MESSAGE_BYTES); \
+ if(at < 0) return at
+
+
+int _syscall_invoke(void);
+void _syscall_debug_putc(char c);
+
+int _syscall_invoke_objdir_nmemb(KernelObjectDirectory *dir, uint8_t *result);
+int _syscall_invoke_objdir_getmemb(KernelObjectDirectory *dir, uint8_t member, obj_type_t *result);
+
+int _syscall_invoke_untyped_size(KernelObjectUntyped *untyped, size_t *bytes);
+int _syscall_invoke_untyped_split(KernelObjectUntyped *path, size_t bytes, KernelObjectUntyped *dest);
+int _syscall_invoke_untyped_merge(KernelObjectUntyped *a, KernelObjectUntyped *b);
+int _syscall_invoke_untyped_alignment(KernelObjectUntyped *path, size_t *alignment);
+
+#endif
diff --git a/lib/libjove/kprintf.c b/lib/libjove/kprintf.c
new file mode 100644
index 0000000..c04756a
--- /dev/null
+++ b/lib/libjove/kprintf.c
@@ -0,0 +1,16 @@
+#include <jove/jove.h>
+#include <jove/syscall.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+void
+jove_kprintf(const char *restrict fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ char buffer[256];
+ vsnprintf(buffer, 256, fmt, ap);
+ va_end(ap);
+
+ for(char *c = buffer; *c; c++) _syscall_debug_putc(*c);
+}
diff --git a/lib/libjove/libjove.c b/lib/libjove/libjove.c
new file mode 100644
index 0000000..fe1c080
--- /dev/null
+++ b/lib/libjove/libjove.c
@@ -0,0 +1,11 @@
+#include "include/jove.h"
+
+uintmax_t _syscall_message_box = 0;
+void *_syscall_message_ptr = 0;
+
+void
+libjove_init(uint64_t box, void *boxptr)
+{
+ _syscall_message_box = box;
+ _syscall_message_ptr = boxptr;
+}
diff --git a/lib/libjove/object/directory.c b/lib/libjove/object/directory.c
new file mode 100644
index 0000000..a9487e8
--- /dev/null
+++ b/lib/libjove/object/directory.c
@@ -0,0 +1,4 @@
+#include <object.h>
+#include <syscall.h>
+
+KernelObjectDirectory __rootdir;
diff --git a/lib/libjove/syscall/debug_putc.c b/lib/libjove/syscall/debug_putc.c
new file mode 100644
index 0000000..2d68ee1
--- /dev/null
+++ b/lib/libjove/syscall/debug_putc.c
@@ -0,0 +1,13 @@
+#include "jove/syscall.h"
+#include "jove/jove.h"
+#include <kernel/syscall.h>
+
+void
+_syscall_debug_putc(char c)
+{
+ *((char*)_syscall_message_ptr) = c;
+ register uint64_t box asm ("rdi") = _syscall_message_box;
+ register uint64_t call asm ("rsi") = SYSCALL_DEBUG_PUTC;
+
+ __asm__ volatile("syscall"::: "memory");
+}
diff --git a/lib/libjove/syscall/invoke-objdir.c b/lib/libjove/syscall/invoke-objdir.c
new file mode 100644
index 0000000..462c282
--- /dev/null
+++ b/lib/libjove/syscall/invoke-objdir.c
@@ -0,0 +1,39 @@
+#include <jove.h>
+#include <object.h>
+#include <path-fromobj.h>
+#include <syscall.h>
+#include <kernel/syscall.h>
+
+int
+_syscall_invoke_objdir_getmemb(KernelObjectDirectory *dir, uint8_t member, obj_type_t *result)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+ obj_type_t *syscall_result;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dir);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_OBJDIR_GETMEMB, uint8_t);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, member, uint8_t);
+ SYSCALL_PAYLOAD_SAVEPTR(syscallData, syscall_at, obj_type_t, syscall_result);
+
+ int status = _syscall_invoke();
+ *result = *syscall_result;
+ return status;
+}
+
+int
+_syscall_invoke_objdir_nmemb(KernelObjectDirectory *dir, uint8_t *result)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+ uint8_t *syscall_result;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dir);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_OBJDIR_NMEMB, uint8_t);
+ SYSCALL_PAYLOAD_SAVEPTR(syscallData, syscall_at, uint8_t, syscall_result);
+
+ int status = _syscall_invoke();
+ *result = *syscall_result;
+
+ return status;
+}
diff --git a/lib/libjove/syscall/invoke-untyped.c b/lib/libjove/syscall/invoke-untyped.c
new file mode 100644
index 0000000..3f718c2
--- /dev/null
+++ b/lib/libjove/syscall/invoke-untyped.c
@@ -0,0 +1,52 @@
+#include <jove.h>
+#include <object.h>
+#include <path-fromobj.h>
+#include <syscall.h>
+#include <kernel/syscall.h>
+#include <string.h>
+
+int
+_syscall_invoke_untyped_size(KernelObjectUntyped *untyped, size_t *bytes)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+ size_t *syscall_bytes;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, untyped);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_UNTYPED_SIZE, uint8_t);
+ SYSCALL_PAYLOAD_SAVEPTR(syscallData, syscall_at, size_t, syscall_bytes);
+
+ int status = _syscall_invoke();
+ *bytes = *syscall_bytes;
+ return status;
+}
+
+int
+_syscall_invoke_untyped_split(KernelObjectUntyped *untyped, size_t bytes, KernelObjectUntyped *dest)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, untyped);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_UNTYPED_SPLIT, uint8_t);
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dest);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, bytes, size_t);
+
+ return _syscall_invoke();
+}
+
+int
+_syscall_invoke_untyped_alignment(KernelObjectUntyped *untyped, size_t *alignment)
+{
+ uint8_t *syscallData = _syscall_message_ptr;
+ int syscall_at = 0;
+ size_t *syscall_alignment;
+
+ SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, untyped);
+ SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_UNTYPED_ALIGNMENT, uint8_t);
+ SYSCALL_PAYLOAD_SAVEPTR(syscallData, syscall_at, size_t, syscall_alignment);
+
+ int status = _syscall_invoke();
+ *alignment = *syscall_alignment;
+ return status;
+}
diff --git a/lib/libjove/syscall/invoke.c b/lib/libjove/syscall/invoke.c
new file mode 100644
index 0000000..e673623
--- /dev/null
+++ b/lib/libjove/syscall/invoke.c
@@ -0,0 +1,14 @@
+#include <syscall.h>
+#include <kernel/syscall.h>
+#include <jove.h>
+
+int
+_syscall_invoke(void)
+{
+ register uint64_t box asm ("rdi") = _syscall_message_box;
+ register uint64_t call asm ("rsi") = SYSCALL_INVOKE;
+
+ int status = 0;
+ __asm__ volatile("syscall": "=a"(status) :: "memory");
+ return status;
+}
diff --git a/lib/libjove/syscall/path-fromobj.c b/lib/libjove/syscall/path-fromobj.c
new file mode 100644
index 0000000..1c0c5d9
--- /dev/null
+++ b/lib/libjove/syscall/path-fromobj.c
@@ -0,0 +1,33 @@
+#include <path-fromobj.h>
+
+int
+path_fromobj_s(KernelObjectTyped *obj, uint8_t *buffer, int size)
+{
+ size_t depth = 0, odepth = 0;
+ for(KernelObjectTyped *o = obj->parent; o; o = o->parent, depth++);
+
+ odepth = depth;
+ if(depth > size) depth = size;
+
+ for(int i = 0; i < depth; i++) {
+ buffer[depth - i - 1] = obj->membi;
+ obj = obj->parent;
+ }
+ return odepth;
+}
+
+int
+path_tobuf(KernelObjectTyped *obj, uint8_t *buffer, size_t at, size_t bufferw)
+{
+ if(at + sizeof(size_t) > bufferw) return -1;
+
+ size_t *buffer_pathW = (size_t*)(&buffer[at]);
+ uint8_t *buffer_path = (uint8_t*)(&buffer_pathW[1]);
+
+ size_t maxDepth = bufferw - (buffer_path - buffer);
+ size_t objDepth = path_fromobj_s(obj, buffer_path, bufferw - (size_t)(buffer_path - buffer));
+ if(objDepth > maxDepth) return -1;
+
+ *buffer_pathW = objDepth;
+ return (int)(buffer_path - buffer) + objDepth;
+}
diff --git a/limine.mk b/limine.mk
new file mode 100644
index 0000000..796c8bd
--- /dev/null
+++ b/limine.mk
@@ -0,0 +1,9 @@
+LIMINE_VERSION := 6.x
+LIMINE_GIT := https://github.com/limine-bootloader/limine.git
+LIMINE_DIR := $(PWD)/limine
+
+all: $(LIMINE_DIR)
+
+$(LIMINE_DIR):
+ git clone $(LIMINE_GIT) --branch=v$(LIMINE_VERSION)-branch-binary --depth=1
+
diff --git a/scripts/binutils-2.41.diff b/scripts/binutils-2.41.diff
new file mode 100644
index 0000000..c63c8c1
--- /dev/null
+++ b/scripts/binutils-2.41.diff
@@ -0,0 +1,77 @@
+diff -rNau binutils-2.41/bfd/config.bfd binutils-2.41-patched/bfd/config.bfd
+--- binutils-2.41/bfd/config.bfd 2023-07-02 19:00:00.000000000 -0400
++++ binutils-2.41-patched/bfd/config.bfd 2024-03-10 23:19:47.522036207 -0400
+@@ -714,6 +714,13 @@
+ targ_selvecs="i386_elf32_vec iamcu_elf32_vec x86_64_elf32_vec i386_pei_vec x86_64_pe_vec x86_64_pei_vec"
+ want64=true
+ ;;
++#ifdef BFD64
++ x86_64-*-jove*)
++ targ_defvec=x86_64_elf64_vec
++ targ_selvecs=i386_elf32_vec
++ want64=true
++ ;;
++#endif
+ x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin)
+ targ_defvec=x86_64_pe_vec
+ targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec pdb_vec"
+diff -rNau binutils-2.41/config.sub binutils-2.41-patched/config.sub
+--- binutils-2.41/config.sub 2023-07-02 19:00:00.000000000 -0400
++++ binutils-2.41-patched/config.sub 2024-03-10 23:33:30.546506756 -0400
+@@ -1758,7 +1758,7 @@
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+- | fiwix* | mlibc* )
++ | fiwix* | mlibc* | jove* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff -rNau binutils-2.41/gas/configure.tgt binutils-2.41-patched/gas/configure.tgt
+--- binutils-2.41/gas/configure.tgt 2023-07-02 19:00:00.000000000 -0400
++++ binutils-2.41-patched/gas/configure.tgt 2024-03-10 23:22:33.351797968 -0400
+@@ -231,6 +231,7 @@
+ i386-*-haiku*) fmt=elf em=haiku ;;
+ i386-*-genode*) fmt=elf ;;
+ i386-*-bsd*) fmt=aout em=386bsd ;;
++ i386-*-jove*) fmt=elf ;;
+ i386-*-netbsd*-gnu* | \
+ i386-*-knetbsd*-gnu | \
+ i386-*-netbsd* | \
+diff -rNau binutils-2.41/ld/configure.tgt binutils-2.41-patched/ld/configure.tgt
+--- binutils-2.41/ld/configure.tgt 2023-07-02 19:00:00.000000000 -0400
++++ binutils-2.41-patched/ld/configure.tgt 2024-03-10 23:24:16.838998259 -0400
+@@ -1053,6 +1053,9 @@
+ targ_extra_ofiles="deffilep.o pdb.o pep-dll.o pe-dll.o"
+ test "$targ" != "$host" && LIB_PATH='${tooldir}/lib/w32api'
+ ;;
++x86_64-*-jove*) targ_emul=elf_x86_64_jove
++ targ_extra_emuls="elf_x86_64"
++ ;;
+ x86_64-*-mingw*) targ_emul=i386pep ;
+ targ_extra_emuls=i386pe
+ targ_extra_ofiles="deffilep.o pdb.o pep-dll.o pe-dll.o"
+diff -rNau binutils-2.41/ld/emulparams/elf_x86_64_jove.sh binutils-2.41-patched/ld/emulparams/elf_x86_64_jove.sh
+--- binutils-2.41/ld/emulparams/elf_x86_64_jove.sh 1969-12-31 19:00:00.000000000 -0500
++++ binutils-2.41-patched/ld/emulparams/elf_x86_64_jove.sh 2024-03-10 23:25:24.152469179 -0400
+@@ -0,0 +1 @@
++source_sh ${srcdir}/emulparams/elf_x86_64.sh
+diff -rNau binutils-2.41/ld/Makefile.am binutils-2.41-patched/ld/Makefile.am
+--- binutils-2.41/ld/Makefile.am 2023-07-02 19:00:00.000000000 -0400
++++ binutils-2.41-patched/ld/Makefile.am 2024-03-10 23:26:41.812851367 -0400
+@@ -455,6 +455,7 @@
+ eelf64tilegx_be.c \
+ eelf_mipsel_haiku.c \
+ eelf_x86_64.c \
++ eelf_x86_64_jove.c \
+ eelf_x86_64_cloudabi.c \
+ eelf_x86_64_fbsd.c \
+ eelf_x86_64_haiku.c \
+@@ -951,6 +951,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx_be.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_mipsel_haiku.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Pc@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_jove.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_cloudabi.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Pc@am__quote@
diff --git a/scripts/buildtools.mk b/scripts/buildtools.mk
new file mode 100644
index 0000000..e3fd46b
--- /dev/null
+++ b/scripts/buildtools.mk
@@ -0,0 +1,63 @@
+BINUTILS_VERSION := 2.41
+GCC_VERSION := 13.2.0
+TOOLCHAIN := x86_64-jove
+
+TOOLDIR := $(PWD)/tools
+SCRIPTDIR := $(PWD)/scripts
+TOOL_SRCDIR := $(TOOLDIR)/src
+TOOL_BUILDDIR := $(TOOLDIR)/build
+SYSROOT_DIR := $(PWD)/sysroot
+
+BINUTILS_ARCHIVE := binutils-$(BINUTILS_VERSION).tar.gz
+BINUTILS_URL := https://ftp.gnu.org/gnu/binutils/$(BINUTILS_ARCHIVE)
+BINUTILS_PATCHFILE := $(SCRIPTDIR)/binutils-$(BINUTILS_VERSION).diff
+BINUTILS_SRCDIR := $(TOOL_SRCDIR)/binutils-$(BINUTILS_VERSION)
+BINUTILS_BUILDDIR := $(TOOL_BUILDDIR)/binutils
+
+GCC_ARCHIVE := gcc-$(GCC_VERSION).tar.gz
+GCC_URL := https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/$(GCC_ARCHIVE)
+GCC_PATCHFILE := $(SCRIPTDIR)/gcc-$(GCC_VERSION).diff
+GCC_SRCDIR := $(TOOL_SRCDIR)/gcc-$(GCC_VERSION)
+GCC_BUILDDIR := $(TOOL_BUILDDIR)/gcc
+
+all: $(TOOLDIR) $(BINUTILS_BUILDDIR) $(GCC_BUILDDIR)
+
+.ONESHELL:
+$(BINUTILS_BUILDDIR): $(BINUTILS_SRCDIR)
+ mkdir -p $(BINUTILS_BUILDDIR)
+ cd $(BINUTILS_BUILDDIR)
+ $(BINUTILS_SRCDIR)/configure --target=$(TOOLCHAIN) --prefix="$(TOOLDIR)" --with-sysroot=$(SYSROOT_DIR) --disable-werror
+ make -j4
+ make install
+
+.PHONY: $(GCC_BUILDDIR)
+.ONESHELL:
+$(GCC_BUILDDIR): $(GCC_SRCDIR)
+ mkdir -p $(GCC_BUILDDIR)
+ cd $(GCC_BUILDDIR)
+ $(GCC_SRCDIR)/configure --target=$(TOOLCHAIN) --prefix="$(TOOLDIR)" --enable-languages=c --with-sysroot=$(SYSROOT_DIR)
+ make all-gcc -j4
+ make all-target-libgcc -j4
+ make install-gcc
+ make install-target-libgcc
+
+$(BINUTILS_SRCDIR): $(TOOLDIR)/$(BINUTILS_ARCHIVE)
+ tar -xzvf $(TOOLDIR)/$(BINUTILS_ARCHIVE) -C $(TOOL_SRCDIR)
+ patch --directory=$(BINUTILS_SRCDIR) --strip=1 < $(BINUTILS_PATCHFILE)
+ cd $(BINUTILS_SRCDIR)/ld && automake
+
+$(GCC_SRCDIR): $(TOOLDIR)/$(GCC_ARCHIVE)
+ tar -xzvf $(TOOLDIR)/$(GCC_ARCHIVE) -C $(TOOL_SRCDIR)
+ patch --directory=$(GCC_SRCDIR) --strip=1 < $(GCC_PATCHFILE)
+ cd $(GCC_SRCDIR) && ./contrib/download_prerequisites
+
+$(TOOLDIR)/$(BINUTILS_ARCHIVE):
+ wget $(BINUTILS_URL) -O $(TOOLDIR)/$(BINUTILS_ARCHIVE)
+
+$(TOOLDIR)/$(GCC_ARCHIVE):
+ wget $(GCC_URL) -O $(TOOLDIR)/$(GCC_ARCHIVE)
+
+$(TOOLDIR):
+ mkdir -p $(TOOLDIR)
+ mkdir -p $(TOOL_SRCDIR)
+ mkdir -p $(TOOL_BUILDDIR)
diff --git a/scripts/gcc-13.2.0.diff b/scripts/gcc-13.2.0.diff
new file mode 100644
index 0000000..d32bf9d
--- /dev/null
+++ b/scripts/gcc-13.2.0.diff
@@ -0,0 +1,86 @@
+diff -rNau gcc-13.2.0/config.sub gcc-13.2.0-patched/config.sub
+--- gcc-13.2.0/config.sub 2023-07-27 04:13:03.000000000 -0400
++++ gcc-13.2.0-patched/config.sub 2024-03-10 23:33:56.596289806 -0400
+@@ -1749,7 +1749,7 @@
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+- | fiwix* )
++ | fiwix* | jove* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff -rNau gcc-13.2.0/fixincludes/mkfixinc.sh gcc-13.2.0-patched/fixincludes/mkfixinc.sh
+--- gcc-13.2.0/fixincludes/mkfixinc.sh 2023-07-27 04:13:03.000000000 -0400
++++ gcc-13.2.0-patched/fixincludes/mkfixinc.sh 2024-03-10 23:49:24.405547826 -0400
+@@ -20,6 +20,7 @@
+ powerpcle-*-eabisim* | \
+ powerpcle-*-eabi* | \
+ *-*-vxworks7* | \
++ *-*-jove* | \
+ *-musl* )
+ # IF there is no include fixing,
+ # THEN create a no-op fixer and exit
+diff -rNau gcc-13.2.0/gcc/config/jove.h gcc-13.2.0-patched/gcc/config/jove.h
+--- gcc-13.2.0/gcc/config/jove.h 1969-12-31 19:00:00.000000000 -0500
++++ gcc-13.2.0-patched/gcc/config/jove.h 2024-03-10 23:44:13.570083205 -0400
+@@ -0,0 +1,17 @@
++#undef TARGET_JOVE
++#define TARGET_JOVE 1
++
++#undef LINK_SPEC
++#define LINK_SPEC "%{shared:-shared} %{static:-static} %{!shared: %{!static: %{rdynamic:-export-dynamic}}}"
++
++#undef LIB_SPEC
++#define LIB_SPEC "--start-group -lc -ljove --end-group"
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC "%{!shared: %{!pg:crt0.o%s}} crti.o%s %{!shared:crtbegin.o%s}"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC "%{!shared:crtend.o%s} crtn.o%s"
++
++#undef OBJECT_FORMAT_ELF
++#define OBJECT_FORMAT_ELF
+diff -rNau gcc-13.2.0/gcc/config.gcc gcc-13.2.0-patched/gcc/config.gcc
+--- gcc-13.2.0/gcc/config.gcc 2023-07-27 04:13:04.000000000 -0400
++++ gcc-13.2.0-patched/gcc/config.gcc 2024-03-10 23:42:11.659119360 -0400
+@@ -843,6 +843,13 @@
+ *-*-fuchsia*)
+ native_system_header_dir=/include
+ ;;
++*-*-jove*)
++ gas=yes
++ gnu_ld=yes
++ default_use_cxa_atexit=yes
++ use_gcc_stdint=provide
++ tmake_file="t-slibgcc"
++ ;;
+ *-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu | *-*-uclinuxfdpiceabi)
+ extra_options="$extra_options gnu-user.opt"
+ gas=yes
+@@ -1891,6 +1897,10 @@
+ x86_64-*-freebsd*)
+ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h"
+ ;;
++x86_64-*-jove*)
++ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/i386elf.h i386/x86-64.h jove.h glibc-stdint.h"
++ tmake_file="${tmake_file} t-slibgcc"
++ ;;
+ i[34567]86-*-netbsdelf*)
+ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${nbsd_tm_file} i386/netbsd-elf.h"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+diff -rNau gcc-13.2.0/libgcc/config.host gcc-13.2.0-patched/libgcc/config.host
+--- gcc-13.2.0/libgcc/config.host 2023-07-27 04:13:07.000000000 -0400
++++ gcc-13.2.0-patched/libgcc/config.host 2024-03-10 23:47:32.669386544 -0400
+@@ -386,6 +386,10 @@
+ esac
+
+ case ${host} in
++x86_64-*-jove*)
++ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
++ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
++ ;;
+ aarch64*-*-elf | aarch64*-*-rtems*)
+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
+ extra_parts="$extra_parts crtfastmath.o"
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..f59b6de
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,30 @@
+{ pkgs ? import <nixpkgs> {} }:
+pkgs.mkShell {
+ name = "jove-build-env";
+ buildInputs = with pkgs; [
+ # Library depends
+ gmp gmp.dev
+ isl
+ libffi libffi.dev
+ libmpc
+ libxcrypt
+ mpfr mpfr.dev
+ xz xz.dev
+ zlib zlib.dev
+
+ m4
+ bison
+ flex
+ texinfo
+ automake115x
+ autoconf269
+
+ gcc
+ stdenv.cc
+ stdenv.cc.libc stdenv.cc.libc_dev
+
+ # Test suite
+ qemu_kvm
+ parted
+ ];
+}
diff --git a/sysroot/boot/initrd.tar b/sysroot/boot/initrd.tar
new file mode 100644
index 0000000..b893e9b
--- /dev/null
+++ b/sysroot/boot/initrd.tar
Binary files differ
diff --git a/sysroot/boot/limine.conf b/sysroot/boot/limine.conf
new file mode 100644
index 0000000..cfe1d54
--- /dev/null
+++ b/sysroot/boot/limine.conf
@@ -0,0 +1,15 @@
+${KERNEL}=boot():/boot/jove.elf
+${INITRD}=boot():/boot/initrd.tar
+
+default_entry: 1
+timeout: 0
+verbose: yes
+
+/Jove
+ protocol: limine
+ kaslr: no
+
+ path: ${KERNEL}
+ cmdline: initrd=/boot/initrd.tar init=/bin/init
+
+ module_path: ${INITRD}