Add EXT2 stub
diff --git a/.gitignore b/.gitignore
index 3c21329..f45649b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@
 **/.#*
 src/kernel/dri/pci/vendors.c
 doc/_build
-!doc/Makefile
\ No newline at end of file
+!doc/Makefile
+mnt/*
diff --git a/include/kernel/dri/fs/ext2/ext2.h b/include/kernel/dri/fs/ext2/ext2.h
new file mode 100644
index 0000000..a94fb77
--- /dev/null
+++ b/include/kernel/dri/fs/ext2/ext2.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <vfs.h>
+
+struct ext2_superblock
+{
+	// Total number of inodes
+	uint total_inodes;
+	// Total number of blocks
+	uint total_blocks;
+	// Number of blocks reserved for superuser
+	uint blocks_reserved_for_superuser;
+	// Number of unallocated blocks
+	uint unallocated_blocks;
+	// Number of unallocated inodes
+	uint unallocated_inodes;
+	// Block number containing the superblock
+	uint superblock_block_number;
+	// the number to shift 1024 to the left by to get the block size
+	uint block_size_shift;
+	// the number to shift 1024 to the left by to get the fragment size
+	uint fragment_size_shift;
+	// Number of blocks in one block group
+	uint blocks_per_block_group;
+	// Number of fragments in one block group
+	uint fragments_per_block_group;
+	// Number of inodse in one block group
+	uint inodes_per_block_group;
+	// UNIX time of last mount
+	uint last_mount_time;
+	// UNIX time of last write
+	uint last_write_time;
+	// Number of mounts since last consistency check
+	ushort mounts_since_last_fsck;
+	// Number of mounts allowed between consistency checks
+	ushort mounts_allowed_before_fsck;
+	// EXT2 signature, should be 0xef53
+	ushort signature;
+	// File system state, see enum ext2_fs_state
+	ushort state;
+	// What to do in case of an error, see enum ext2_error_case
+	ushort error_case;
+	// Minor portion of version
+	ushort version_minor;
+	// UNIX time of last consistency check
+	uint last_fsck_time;
+	// Max time between consistency checks
+	uint fsck_time_interval;
+	// Operating system ID of creator
+	uint creator_os_id;
+	// Major portion of version
+	uint version_major;
+	// User ID that can use reserved blocks
+	ushort reserved_blocks_uid;
+	// Group ID that can use reserved blocks
+	ushort reserved_blocks_gid;
+};
+
+enum ext2_fs_state
+{
+	EXT2_STATE_CLEAN = 1,
+	EXT2_STATE_ERRORS = 2,
+};
+
+enum ext2_error_case
+{
+	EXT2_ERROR_IGNORE = 1,
+	EXT2_ERROR_REMOUNT = 2,
+	EXT2_ERROR_KPANIC = 3,
+};
+
+enum ext2_os_id
+{
+	EXT2_OS_LINUX = 0,
+	EXT2_OS_HURD,
+	EXT2_OS_MASIX,
+	EXT2_OS_FREEBSD,
+	EXT2_OS_OTHER_BSD,
+};
+
+void ext2_mount(struct fs_node *where);
diff --git a/include/kernel/dri/ide/ide.h b/include/kernel/dri/ide/ide.h
index 0283999..3376cb5 100644
--- a/include/kernel/dri/ide/ide.h
+++ b/include/kernel/dri/ide/ide.h
@@ -2,4 +2,18 @@
 
 #include <dri/pci/pci.h>
 
+enum ide_mode
+{
+    IDE_PCI_NATIVE,
+    IDE_COMPAT,
+};
+
+struct ide_device
+{
+    enum ide_mode channel_mode[2];
+    bool channel_mode_modifiable[2];
+    bool supports_dma;
+};
+
 void ide_register();
+void ide_print_device(struct ide_device *dev);
diff --git a/src/kernel/vfs.h b/include/kernel/vfs.h
similarity index 100%
rename from src/kernel/vfs.h
rename to include/kernel/vfs.h
diff --git a/src/kernel/Jmk b/src/kernel/Jmk
index 3759fd6..a821bae 100644
--- a/src/kernel/Jmk
+++ b/src/kernel/Jmk
@@ -24,7 +24,7 @@
 
 LDFLAGS += -Tlink.ld -melf_i386
 ASMFLAGS += -felf -Fdwarf
-QEMUFLAGS = -d cpu_reset
+QEMUFLAGS = -d cpu_reset -hda hd0.img
 
 OBJECTS = 	boot.o \
 			main.o \
@@ -64,7 +64,12 @@
 	gdb $<
 	@pkill qemu-system-i38
 
-qemu: kernel.elf
+hd0.img:
+	status_log(MKFS, $@)
+	@dd bs=4M count=8 if=/dev/zero of=$@
+	@mkfs.ext2 $@
+
+qemu: kernel.elf hd0.img
 	qemu-system-i386 $(QEMUFLAGS) -monitor stdio -kernel kernel.elf -no-reboot
 
 qemu-iso: install
@@ -73,6 +78,16 @@
 scan_codes.c: gen_scan_codes.py scan_codes.tsv 
 	python3 $< > $@
 
+mount: hd0.img
+	status_log(MOUNT, $^ $(ROOT)/mnt)
+	@mkdir -p $(ROOT)/mnt
+	@mount $^ $(ROOT)/mnt
+	@if [ $$(whoami) = root ]; then echo 'You ran this as root, you probably want to chown $(ROOT)/mnt now.'; fi
+
+umount:
+	status_log(UMOUNT, $(ROOT)/mnt)
+	@umount $(ROOT)/mnt
+
 install: kernel.elf lib(initrd)
 	cp kernel.elf $(ROOT)/boot/
 	rm -f $(ROOT)/bin/bluejay.iso
diff --git a/src/kernel/dri/ata_pio/ata_pio.c b/src/kernel/dri/ata_pio/ata_pio.c
index cd45998..db1b7cb 100644
--- a/src/kernel/dri/ata_pio/ata_pio.c
+++ b/src/kernel/dri/ata_pio/ata_pio.c
@@ -3,18 +3,23 @@
 #include <io.h>
 #include <log.h>
 
+/* TODO: Rewrite all of this to work with dri_ide in the case of multiple
+ * devices */
+
 static ushort test_buffer[256];
 
 void ata_pio_wait_bsy()
 {
 	while (inb(ATA_PORT_CMD) & ATA_BSY)
-	{}
+	{
+	}
 }
 
 void ata_pio_wait_drq()
 {
 	while (!(inb(ATA_PORT_CMD) & ATA_RDY))
-	{}
+	{
+	}
 }
 
 uint ata_pio_get_error()
@@ -40,9 +45,7 @@
 
 	ata_pio_wait_bsy();
 
-	asm volatile("rep insw" ::
-				 "c"(num_sectors * 256),
-				 "d"(ATA_PORT_DATA),
+	asm volatile("rep insw" ::"c"(num_sectors * 256), "d"(ATA_PORT_DATA),
 				 "D"(buffer));
 
 	ata_pio_wait_bsy();
@@ -57,9 +60,7 @@
 
 	ata_pio_wait_bsy();
 
-	asm volatile("rep outsw" ::
-				 "c"(num_sectors * 256),
-				 "d"(ATA_PORT_DATA),
+	asm volatile("rep outsw" :: "c"(num_sectors * 256), "d"(ATA_PORT_DATA),
 				 "S"(buffer));
 }
 
@@ -83,8 +84,8 @@
 	for (int i = 0; i < 256; i++)
 		test_buffer[i] = i;
 
-	ata_pio_write_sectors(0, 1, test_buffer);
+	// ata_pio_write_sectors(0, 1, test_buffer);
 
-	ata_pio_read_sectors(test_buffer, 0, 1);
-	print_buffer();
+	// ata_pio_read_sectors(test_buffer, 0, 1);
+	// print_buffer();
 }
diff --git a/src/kernel/dri/fs/ext2/Jmk b/src/kernel/dri/fs/ext2/Jmk
new file mode 100644
index 0000000..b0da0c3
--- /dev/null
+++ b/src/kernel/dri/fs/ext2/Jmk
@@ -0,0 +1,17 @@
+init(ext2, ext2.a)
+
+preset(freestanding)
+preset(optimize)
+preset(debug)
+preset(32)
+preset(warn)
+
+archetype(c)
+
+CFLAGS += -I/include/kernel
+
+OBJECTS = ext2.o
+
+type(static_lib)
+
+finish
diff --git a/src/kernel/dri/fs/ext2/ext2.c b/src/kernel/dri/fs/ext2/ext2.c
new file mode 100644
index 0000000..eb6842b
--- /dev/null
+++ b/src/kernel/dri/fs/ext2/ext2.c
@@ -0,0 +1,7 @@
+#include <dri/fs/ext2/ext2.h>
+#include <kint.h>
+
+void ext2_mount(struct fs_node *where)
+{
+	// TODO
+}
diff --git a/src/kernel/dri/ide/ide.c b/src/kernel/dri/ide/ide.c
index b42873d..21f2651 100644
--- a/src/kernel/dri/ide/ide.c
+++ b/src/kernel/dri/ide/ide.c
@@ -14,9 +14,25 @@
     return dev->class == 1 && dev->subclass == 1;
 }
 
+void ide_print_device(struct ide_device *dev)
+{
+    kprintf("<ide-device dma=%b>", dev->supports_dma);
+}
+
 void ide_thread(struct ide_thread_data *data)
 {
     kprintf("IDE driver thread starting: device=0x%x\n", data->dev.device_id);
+
+    struct ide_device dev;
+
+    uchar p = data->dev.prog_if;
+    dev.channel_mode[0] = p & 1;
+    dev.channel_mode_modifiable[0] = p & (1 << 1);
+    dev.channel_mode[1] = p & (1 << 2);
+    dev.channel_mode_modifiable[1] = p & (1 << 3);
+    dev.supports_dma = p & (1 << 7);
+
+    ide_print_device(&dev);
 }
 
 void ide_init(struct pci_device dev, uchar bus, uchar slot, uchar func)
diff --git a/src/kernel/log.c b/src/kernel/log.c
index ac49971..11ce505 100644
--- a/src/kernel/log.c
+++ b/src/kernel/log.c
@@ -40,6 +40,13 @@
 				vga_put(s);
 				break;
 			}
+			case 'b': {
+				uint v = va_arg(args, uint);
+				if (v)
+					vga_write("true");
+				else
+					vga_write("false");
+			}
 			}
 			format++;
 		}