Use JMK build system
diff --git a/.gitignore b/.gitignore
index bdf8adf..77a9e09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,8 +4,9 @@
 *.o
 *.a
 *.so
-compile_commands.json
+**/compile_commands.json
 **/.clangd
 *.img
 bin/*
-!bin/*.txt
\ No newline at end of file
+!bin/jmk
+**/Makefile
\ No newline at end of file
diff --git a/bin/bin.txt b/bin/bin.txt
deleted file mode 100644
index 9996874..0000000
--- a/bin/bin.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This directory holds system and user binaries.
-Bluejay.iso will be built here.
diff --git a/bin/jmk b/bin/jmk
new file mode 100755
index 0000000..ffd3993
--- /dev/null
+++ b/bin/jmk
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Jay MaKe
+
+dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
+root="$(dirname $dir)"
+jmkscript="$root/share/jmk/jmk.m4"
+
+for file in $(find -name Jmk); do
+    echo "Processing $file" > /dev/stderr
+    outdir="$(dirname $file)"
+    m4 -D jmk_root="$root" -D jmk_build_cmd="$0" -D jmk_build_dir="$(pwd)" "$jmkscript" "$file" > "$outdir/Makefile" || exit 1
+done
diff --git a/boot/grub/grub.cfg b/boot/grub/grub.cfg
index 856a4ea..a1d5fb0 100644
--- a/boot/grub/grub.cfg
+++ b/boot/grub/grub.cfg
@@ -1,6 +1,6 @@
 menuentry "Bluejay" {
           multiboot /boot/kernel.elf
-          module /boot/initrd.img
+          module /boot/initrd/initrd.img
 }
 
 set timeout=1
diff --git a/boot/initrd/Jmk b/boot/initrd/Jmk
new file mode 100644
index 0000000..de65cb5
--- /dev/null
+++ b/boot/initrd/Jmk
@@ -0,0 +1,10 @@
+init(initrd, initrd.img)
+
+depends(mkinitrd, $(ROOT)/src/mkinitrd, mkinitrd)
+
+SOURCES = config
+
+initrd.img: $(SOURCES) | lib(mkinitrd)
+	lib(mkinitrd) $@ $^
+
+finish
diff --git a/boot/initrd/Makefile b/boot/initrd/Makefile
index 59f82ae..5a317fd 100644
--- a/boot/initrd/Makefile
+++ b/boot/initrd/Makefile
@@ -1,10 +1,30 @@
+jmk_project := initrd
+jmk_target = initrd.img
+ROOT := /home/ch/dev/bluejay
+ASM ?= nasm
+CC ?= gcc
+LD ?= ld
+CFLAGS += -I$(ROOT)/include
+
+all: $(jmk_target)
+
+
+jmk_lib_path_mkinitrd = $(ROOT)/src/mkinitrd
+jmk_lib_target_mkinitrd = mkinitrd
+jmk_libs_phony += $(jmk_lib_path_mkinitrd)/$(jmk_lib_target_mkinitrd)
+
+$(jmk_lib_path_mkinitrd)/$(jmk_lib_target_mkinitrd):
+	$(MAKE) -C $(jmk_lib_path_mkinitrd) $(jmk_lib_target_mkinitrd)
+
 SOURCES = config
-JAYROOT = ../../
 
-initrd.img: $(SOURCES) | $(JAYROOT)/bin/mkinitrd
-	$(JAYROOT)/bin/mkinitrd $@ $^
+initrd.img: $(SOURCES) | $(jmk_lib_path_mkinitrd)/$(jmk_lib_target_mkinitrd)
+	$(jmk_lib_path_mkinitrd)/$(jmk_lib_target_mkinitrd) $@ $^
 
-$(JAYROOT)/bin/mkinitrd:
-	$(MAKE) -C $(JAYROOT)/src/mkinitrd install
+clean:
+	rm -f *.o *.a *.so $(jmk_target)
 
-.PHONY: $(JAYROOT)/bin/mkinitrd
+Makefile: Jmk
+	cd "/home/ch/dev/bluejay" && ./bin/jmk
+
+.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) clean all
diff --git a/share/jmk/jmk.m4 b/share/jmk/jmk.m4
new file mode 100644
index 0000000..b454398
--- /dev/null
+++ b/share/jmk/jmk.m4
@@ -0,0 +1,89 @@
+divert(-1)
+
+dnl
+dnl JMK (Jay MaKe) build system
+dnl
+
+define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')')
+define(`_arg1', `$1')
+define(`_foreach', `ifelse(`$2', `()', `',
+  `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')
+
+
+
+define(init,
+`jmk_project := $1
+jmk_target = ifelse(`$#', 2, $2, $1)
+ROOT := jmk_root
+ASM ?= nasm
+CC ?= gcc
+LD ?= ld
+CFLAGS += -I$(ROOT)/include
+
+all: $(jmk_target)')
+
+dnl preset applies a certain configuration preset to the project
+define(preset,
+    `ifelse($1, `freestanding',
+        `CFLAGS += -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding',
+        $1, `optimize', `CFLAGS += -O2',
+        $1, `debug', `CFLAGS += -g',
+        $1, `32', `CFLAGS += -m32',
+        $1, `warn', `CFLAGS += -Wall -Wno-unused-function -Wno-unused-variable',
+        $1, `nasm', `ASM = nasm'
+    )')
+
+dnl this is really, really terrible, but to my knowledge there is no
+dnl other way to escape a $. The manual says nothing about this.
+define(ident, $1)
+define(dollar_at, `ident($)ident(@)')
+
+dnl archetype enables a language archetype
+define(archetype,
+    `ifelse($1, c, `.c.o:
+	$(CC) -c $< -o dollar_at $(CFLAGS)',
+        $1, asm, `.s.o:
+	$(ASM) $(ASMFLAGS) $< -o dollar_at'
+    )'
+)
+
+dnl depends declares an external dependency
+define(`depends', `
+jmk_lib_path_$1 = $2
+jmk_lib_target_$1 = ifelse($3, `', $1.a, $3)
+jmk_libs_phony += $(jmk_lib_path_$1)/$(jmk_lib_target_$1)
+
+$(jmk_lib_path_$1)/$(jmk_lib_target_$1):
+	$(MAKE) -C $(jmk_lib_path_$1) $(jmk_lib_target_$1)')
+
+dnl lib is used to list an external dependency declared with depends()
+define(`lib', `$(jmk_lib_path_$1)/$(jmk_lib_target_$1)')
+
+define(`phony', `jmk_custom_phony += $1')
+
+dnl type is used to specify the target type
+define(type,
+    `ifelse($1, executable,
+`$(jmk_target): $(OBJECTS)
+	$(CC) -o dollar_at $^ $(CFLAGS)',
+    $1, static_lib,
+`$(jmk_target): $(OBJECTS)
+	ar rcs dollar_at $^',
+    $1, custom_link,
+`$(jmk_target): $(OBJECTS)
+	$(LD) $(LDFLAGS) -o dollar_at $^'
+    )')
+
+dnl finish is required at the end of the Jmk file to generate some
+dnl final declarations
+
+define(finish,
+`clean:
+	rm -f *.o *.a *.so $(jmk_target)
+
+Makefile: Jmk
+	cd "jmk_build_dir" && jmk_build_cmd
+
+.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) clean all')
+
+divert(0)dnl
diff --git a/src/kernel/Jmk b/src/kernel/Jmk
new file mode 100644
index 0000000..c8ac4fe
--- /dev/null
+++ b/src/kernel/Jmk
@@ -0,0 +1,61 @@
+init(kernel, kernel.elf)
+
+preset(freestanding)
+preset(optimize)
+preset(debug)
+preset(32)
+preset(warn)
+preset(nasm)
+
+archetype(c)
+archetype(asm)
+
+depends(initrd, $(ROOT)/boot/initrd, initrd.img)
+
+LDFLAGS = -Tlink.ld -melf_i386
+ASMFLAGS = -felf
+QEMUFLAGS = -d cpu_reset
+
+OBJECTS = 	boot.o \
+			main.o \
+			descriptor_tables.o \
+			io.o \
+			vga.o \
+			gdt_flush.o \
+			idt.o \
+			log.o \
+			irq.o \
+			pic.o \
+			timer.o \
+			paging.o \
+			switch_table.o \
+			scan_codes.o \
+			kheap.o \
+			alloc.o \
+			vfs.o \
+			multiboot.o \
+			vfs_initrd.o
+
+type(custom_link)
+
+debug: kernel.elf
+	qemu-system-i386 -s -S -kernel kernel.elf &
+	@echo run "target remote localhost:1234" to connect to qemu
+	gdb
+	@pkill qemu-system-i38
+
+qemu: kernel.elf
+	qemu-system-i386 $(QEMUFLAGS) -monitor stdio -kernel kernel.elf -no-reboot
+
+qemu-iso: install
+	qemu-system-i386 $(QEMUFLAGS) -monitor stdio $(ROOT)/bin/bluejay.iso
+
+scan_codes.c: gen_scan_codes.py scan_codes.tsv 
+	python3 $< > $@
+
+install: kernel.elf lib(initrd)
+	cp kernel.elf $(ROOT)/boot/
+	rm -f $(ROOT)/bin/bluejay.iso
+	grub-mkrescue -o $(ROOT)/bin/bluejay.iso $(ROOT)
+
+finish
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 9029f26..ebac3b5 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -1,4 +1,42 @@
-SOURCES = 	boot.o \
+jmk_project := kernel
+jmk_target = kernel.elf
+ROOT := /home/ch/dev/bluejay
+ASM ?= nasm
+CC ?= gcc
+LD ?= ld
+CFLAGS += -I$(ROOT)/include
+
+all: $(jmk_target)
+
+CFLAGS += -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding
+CFLAGS += -O2
+CFLAGS += -g
+CFLAGS += -m32
+CFLAGS += -Wall -Wno-unused-function -Wno-unused-variable
+ASM = nasm
+    
+
+.c.o:
+	$(CC) -c $< -o $@ $(CFLAGS)
+
+.s.o:
+	$(ASM) $(ASMFLAGS) $< -o $@
+    
+
+
+
+jmk_lib_path_initrd = $(ROOT)/boot/initrd
+jmk_lib_target_initrd = initrd.img
+jmk_libs_phony += $(jmk_lib_path_initrd)/$(jmk_lib_target_initrd)
+
+$(jmk_lib_path_initrd)/$(jmk_lib_target_initrd):
+	$(MAKE) -C $(jmk_lib_path_initrd) $(jmk_lib_target_initrd)
+
+LDFLAGS = -Tlink.ld -melf_i386
+ASMFLAGS = -felf
+QEMUFLAGS = -d cpu_reset
+
+OBJECTS = 	boot.o \
 			main.o \
 			descriptor_tables.o \
 			io.o \
@@ -18,19 +56,9 @@
 			multiboot.o \
 			vfs_initrd.o
 
-JAYROOT = ../../
-CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding \
-			-m32 -O2 -g -Wall -Wno-unused-function -Wno-unused-variable \
-			-I$(JAYROOT)/include
-LDFLAGS = -Tlink.ld -melf_i386
-ASMFLAGS = -felf
-QEMUFLAGS = -d cpu_reset
-
-kernel.elf: $(SOURCES)
-	ld $(LDFLAGS) -o $@ $^
-
-clean:
-	rm -f *.o *.bin *.elf $(JAYROOT)/bin/*.iso
+$(jmk_target): $(OBJECTS)
+	$(LD) $(LDFLAGS) -o $@ $^
+    
 
 debug: kernel.elf
 	qemu-system-i386 -s -S -kernel kernel.elf &
@@ -42,21 +70,20 @@
 	qemu-system-i386 $(QEMUFLAGS) -monitor stdio -kernel kernel.elf -no-reboot
 
 qemu-iso: install
-	qemu-system-i386 $(QEMUFLAGS) -monitor stdio $(JAYROOT)/bin/bluejay.iso
+	qemu-system-i386 $(QEMUFLAGS) -monitor stdio $(ROOT)/bin/bluejay.iso
 
 scan_codes.c: gen_scan_codes.py scan_codes.tsv 
 	python3 $< > $@
 
-.s.o:
-	nasm $(ASMFLAGS) $<
+install: kernel.elf $(jmk_lib_path_initrd)/$(jmk_lib_target_initrd)
+	cp kernel.elf $(ROOT)/boot/
+	rm -f $(ROOT)/bin/bluejay.iso
+	grub-mkrescue -o $(ROOT)/bin/bluejay.iso $(ROOT)
 
-$(JAYROOT)/boot/initrd.img:
-	$(MAKE) -C $(JAYROOT)/boot/initrd initrd.img
-	cp $(JAYROOT)/boot/initrd/initrd.img $(JAYROOT)/boot/
+clean:
+	rm -f *.o *.a *.so $(jmk_target)
 
-install: kernel.elf $(JAYROOT)/boot/initrd.img
-	cp kernel.elf $(JAYROOT)/boot/
-	rm -f $(JAYROOT)/bin/bluejay.iso
-	grub-mkrescue -o $(JAYROOT)/bin/bluejay.iso $(JAYROOT)
+Makefile: Jmk
+	cd "/home/ch/dev/bluejay" && ./bin/jmk
 
-.PHONY: install qemu clean qemu-iso debug $(JAYROOT)/boot/initrd.img
+.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) clean all
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 2ee2828..ead5232 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -26,30 +26,25 @@
 
 	// Load initrd
 	struct multiboot_info mb = make_multiboot_physical(mboot);
+	init_vfs();
 
+#ifdef INITRD
 	kassert(mb.mods_count, "No multiboot modules loaded!");
 	kprintf("mboot->mods_addr = %d (0x%x)\n", mb.mods_addr, mb.mods_addr);
 	uchar *initrd_loc = (uchar *)((uint *)mb.mods_addr)[0];
 
 	kprintf("initrd is at 0x%x to 0x%x\n", initrd_loc);
 
-	kprintf("%x |", initrd_loc);
-	for (int i = 0; i < 32; i++)
-	{
-		kprintf(" %x", initrd_loc[i]);
-		if (i % 8 == 0)
-			kprintf("\n");
-	}
-	kprintf("\n");
+	init_initrd_vfs(initrd_loc);
+#endif
 
-	init_vfs();
-	//init_initrd_vfs(initrd_loc);
 	kprintf("VFS initialized\n");
 
 	vga_set_color(LIGHT_GREEN, BLACK);
-	vga_write("Setup complete!\n");
+	kprintf("Setup complete!\n");
 	vga_set_color(WHITE, BLACK);
 
+#ifdef TEST_VFS_INITRD
 	kprintf("fs_readdir(\"/dev/initrd\")\n");
 
 	struct fs_dirent dirent;
@@ -57,6 +52,7 @@
 	{
 		kprintf("name: %s, inode: %d\n", dirent.name, dirent.inode);
 	}
+#endif
 
 	asm volatile("sti");
 
diff --git a/src/mkinitrd/Jmk b/src/mkinitrd/Jmk
new file mode 100644
index 0000000..fa8acc2
--- /dev/null
+++ b/src/mkinitrd/Jmk
@@ -0,0 +1,16 @@
+init(mkinitrd)
+
+preset(optimize)
+preset(warn)
+
+archetype(c)
+
+OBJECTS = main.o
+
+phony(install)
+install: mkinitrd
+	cp $< $(ROOT)/bin
+
+type(executable)
+
+finish
diff --git a/src/mkinitrd/Makefile b/src/mkinitrd/Makefile
index b121b75..a003dff 100644
--- a/src/mkinitrd/Makefile
+++ b/src/mkinitrd/Makefile
@@ -1,14 +1,33 @@
+jmk_project := mkinitrd
+jmk_target = mkinitrd
+ROOT := /home/ch/dev/bluejay
+ASM ?= nasm
+CC ?= gcc
+LD ?= ld
+CFLAGS += -I$(ROOT)/include
+
+all: $(jmk_target)
+
+CFLAGS += -O2
+CFLAGS += -Wall -Wno-unused-function -Wno-unused-variable
+
+.c.o:
+	$(CC) -c $< -o $@ $(CFLAGS)
+
+
 OBJECTS = main.o
-JAYROOT = ../../
-CFLAGS = -O2 -I$(JAYROOT)/include -Wall
 
-mkinitrd: $(OBJECTS)
-	$(CC) -o $@ $^
-
+jmk_custom_phony += install
 install: mkinitrd
-	cp mkinitrd $(JAYROOT)/bin
+	cp $< $(ROOT)/bin
+
+$(jmk_target): $(OBJECTS)
+	$(CC) -o $@ $^ $(CFLAGS)
 
 clean:
-	rm -f *.o mkinitrd
+	rm -f *.o *.a *.so $(jmk_target)
 
-.PHONY: clean install
+Makefile: Jmk
+	cd "/home/ch/dev/bluejay" && ./bin/jmk
+
+.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) clean all