Initial commit
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..7383c59
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,22 @@
+SOURCES = boot.o main.o descriptor_tables.o mem.o vga.o gdt_flush.o idt.o interrupts.o
+CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -O2 -g
+LDFLAGS = -Tlink.ld -melf_i386
+ASMFLAGS = -felf
+
+kernel.elf: $(SOURCES)
+	ld $(LDFLAGS) -o $@ $^
+
+clean:
+	rm -f *.o *.bin *.elf
+
+qemu: install
+	qemu-system-i386 -monitor stdio ../bin/bluejay.iso
+
+.s.o:
+	nasm $(ASMFLAGS) $<
+
+install: kernel.elf
+	cp kernel.elf ../boot/
+	grub-mkrescue -o ../bin/bluejay.iso ..
+
+.PHONY: install qemu clean
diff --git a/src/boot.s b/src/boot.s
new file mode 100644
index 0000000..5c4381c
--- /dev/null
+++ b/src/boot.s
@@ -0,0 +1,37 @@
+;;; GRUB Multiboot header, calls main() in main.c
+
+MBOOT_PAGE_ALIGN    equ 1<<0
+MBOOT_MEM_INFO      equ 1<<1
+MBOOT_HEADER_MAGIC  equ 0x1BADB002
+
+MBOOT_HEADER_FLAGS  equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO
+MBOOT_CHECKSUM      equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)
+
+
+	[bits 32]
+
+	[global mboot]
+	[extern code]
+	[extern bss]
+	[extern end]
+
+mboot:
+	dd  MBOOT_HEADER_MAGIC ; This tells GRUB to start executing here:
+	dd  MBOOT_HEADER_FLAGS
+	dd  MBOOT_CHECKSUM
+   
+	dd  mboot                   ; Current location
+	dd  code                    ; .text section
+	dd  bss                     ; End of .data
+	dd  end                     ; End of kernel
+	dd  start
+
+	[global start]
+	[extern main]				; C code
+
+start:
+	push ebx					; Holds multiboot header location
+
+	cli
+	call main
+	jmp $
diff --git a/src/descriptor_tables.c b/src/descriptor_tables.c
new file mode 100644
index 0000000..3b121b1
--- /dev/null
+++ b/src/descriptor_tables.c
@@ -0,0 +1,124 @@
+#include "descriptor_tables.h"
+#include "vga.h"
+#include "mem.h"
+
+extern void gdt_flush(uint gdt);
+extern void idt_flush(uint idt);
+
+static void gdt_set_gate(uint i, uint base, uint limit, uchar access, uchar gran);
+static void idt_set_gate(uchar num, uint base, ushort selector, uchar flags);
+
+struct gdt_entry gdt_entries[5];
+struct gdt_pointer gdt_pointer;
+
+struct idt_entry idt_entries[256];
+struct idt_pointer idt_pointer;
+
+static void (* isrs[32])() =
+{
+	isr0,
+	isr1,
+	isr2,
+	isr3,
+	isr4,
+	isr5,
+	isr6,
+	isr7,
+	isr8,
+	isr9,
+	isr10,
+	isr11,
+	isr12,
+	isr13,
+	isr14,
+	isr15,
+	isr16,
+	isr17,
+	isr18,
+	isr19,
+	isr20,
+	isr21,
+	isr22,
+	isr23,
+	isr24,
+	isr25,
+	isr26,
+	isr27,
+	isr28,
+	isr29,
+	isr30,
+	isr31
+};
+
+void init_gdt()
+{
+	gdt_pointer.limit = sizeof(struct gdt_entry) * 5 - 1;
+	gdt_pointer.base = (uint)&gdt_entries;
+
+	gdt_set_gate(0, 0, 0, 0, 0);          // Null segment
+	gdt_set_gate(1, 0, ~0, 0x9a, 0xcf);   // Code segment
+	gdt_set_gate(2, 0, ~0, 0x92, 0xcf);   // Data segment
+	gdt_set_gate(3, 0, ~0, 0xfa, 0xcf);   // User mode code segment
+	gdt_set_gate(4, 0, ~0, 0xf2, 0xcf);   // User mode data segment
+
+	gdt_flush((uint) &gdt_pointer);
+
+	vga_write("GDT Initialized\n");
+}
+
+static void gdt_set_gate(uint i, uint base, uint limit, uchar access, uchar gran)
+{
+	struct gdt_entry *e = &gdt_entries[i];
+
+	e->base_low = base & 0xffff;
+	e->base_middle = (base >> 16) & 0xff;
+	e->base_high = (base >> 24) & 0xff;
+
+	e->limit_low = limit & 0xffff;
+	e->granularity = ((limit >> 16) & 0x0f) | (gran & 0xf0);
+
+	e->access = access;
+}
+
+void init_idt()
+{
+	idt_pointer.limit = sizeof(struct idt_entry) * 256 - 1;
+	idt_pointer.base = (uint)&idt_entries;
+
+	memset(&idt_entries, 0, sizeof(idt_entries));
+
+	vga_write("sizeof(idt_entries) = ");
+	vga_putx(sizeof(idt_entries));
+	vga_put('\n');
+
+	vga_write("isr0 = ");
+	vga_putx((uint)isrs[0]);
+	vga_put('\n');
+
+	for (int i = 0; i < 32; i++)
+	{
+		idt_set_gate(i, (uint)isrs[i], 0x08, 0x8e);
+	}
+
+	idt_flush((uint)&idt_pointer);
+
+	vga_write("IDT Initialized!\n");
+}
+
+static void idt_set_gate(uchar num, uint base, ushort selector, uchar flags)
+{
+	struct idt_entry *e = &idt_entries[num];
+
+	e->base_low = base & 0xffff;
+	e->base_high = (base >> 16) & 0xffff;
+
+	e->selector = selector;
+	e->zero = 0;
+	e->flags = flags /* | 0x60 */;
+}
+
+void init_descriptor_tables()
+{
+	init_gdt();
+	init_idt();
+}
diff --git a/src/descriptor_tables.h b/src/descriptor_tables.h
new file mode 100644
index 0000000..d918f4a
--- /dev/null
+++ b/src/descriptor_tables.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include "kint.h"
+
+struct gdt_entry
+{
+	ushort limit_low;
+	ushort base_low;
+	uchar base_middle;
+
+	union
+	{
+		struct
+		{
+			uint a_p    : 1;
+			uint a_dpl  : 2;
+			uint a_dt   : 1;
+			uint a_type : 4;
+		};
+
+		uchar access;
+	};
+
+	union
+	{
+		struct
+		{
+			uint g_g    : 1;
+			uint g_d    : 1;
+			uint g_zero : 2; /* includes A */
+			uint g_len  : 4;
+		};
+		
+		uchar granularity;
+	};
+
+	uchar base_high;
+} __attribute__((packed));
+
+
+struct gdt_pointer
+{
+	/* Upper 16 bits of selector limits */
+	ushort limit;
+	/* first struct gdt_entry */
+	uint base;
+} __attribute__((packed));
+
+struct idt_entry
+{
+	ushort base_low;
+	ushort selector;
+	uchar zero;
+
+	union
+	{
+		struct
+		{
+			uchar f_p     : 1;
+			uchar f_dpl   : 2;
+			uchar f_const : 5;
+		};
+		
+		uchar flags;
+	};
+	
+	ushort base_high;
+} __attribute__((packed));
+
+#define IDT_F_CONST 0b00110
+
+struct idt_pointer
+{
+	ushort limit;
+	uint base;
+} __attribute__((packed));
+
+extern void isr0();
+extern void isr1();
+extern void isr2();
+extern void isr3();
+extern void isr4();
+extern void isr5();
+extern void isr6();
+extern void isr7();
+extern void isr8();
+extern void isr9();
+extern void isr10();
+extern void isr11();
+extern void isr12();
+extern void isr13();
+extern void isr14();
+extern void isr15();
+extern void isr16();
+extern void isr17();
+extern void isr18();
+extern void isr19();
+extern void isr20();
+extern void isr21();
+extern void isr22();
+extern void isr23();
+extern void isr24();
+extern void isr25();
+extern void isr26();
+extern void isr27();
+extern void isr28();
+extern void isr29();
+extern void isr30();
+extern void isr31();
+
+
+void init_descriptor_tables();
+void init_idt();
+void init_gdt();
diff --git a/src/gdt_flush.s b/src/gdt_flush.s
new file mode 100644
index 0000000..f1dd8ac
--- /dev/null
+++ b/src/gdt_flush.s
@@ -0,0 +1,17 @@
+	[bits 32]
+	[global gdt_flush]
+
+gdt_flush:
+	mov eax, [esp + 4]
+	lgdt [eax]					; Load GDT
+
+	mov ax, 0x10				; Offset of data segment
+	mov ds, ax,
+	mov es, ax
+	mov fs, ax
+	mov gs, ax
+	mov ss, ax
+
+	jmp 0x08:.flush				; Implicitly reloads the code segment
+.flush:
+	ret
diff --git a/src/idt.s b/src/idt.s
new file mode 100644
index 0000000..756eed4
--- /dev/null
+++ b/src/idt.s
@@ -0,0 +1,84 @@
+	[bits 32]
+	[global idt_flush]
+
+idt_flush:
+	mov eax, [esp + 4]
+	lidt [eax]
+	ret
+
+%macro ISRNOERR 1
+	[global isr%1]
+isr%1:
+	cli
+	push byte 0
+	push byte %1
+	jmp isr_common
+%endmacro
+
+%macro ISRERR 1
+	[global isr%1]
+isr%1:
+	cli
+	push byte %1
+	jmp isr_common
+%endmacro
+
+ISRNOERR 0
+ISRNOERR 1
+ISRNOERR 2
+ISRNOERR 3
+ISRNOERR 4
+ISRNOERR 5
+ISRNOERR 6
+ISRNOERR 7
+ISRERR 8
+ISRNOERR 9
+ISRERR 10
+ISRERR 11
+ISRERR 12
+ISRERR 13
+ISRERR 14
+ISRNOERR 15
+ISRNOERR 16
+ISRNOERR 17
+ISRNOERR 18
+ISRNOERR 19
+ISRNOERR 20
+ISRNOERR 21
+ISRNOERR 22
+ISRNOERR 23
+ISRNOERR 24
+ISRNOERR 25
+ISRNOERR 26
+ISRNOERR 27
+ISRNOERR 28
+ISRNOERR 29
+ISRNOERR 30
+ISRNOERR 31
+
+
+	[extern isr_handler]
+isr_common:
+	pusha						; Save all registers
+
+	mov ax, ds
+	push eax
+
+	mov ax, 0x10
+	mov ds, ax
+	mov es, ax
+	mov fs, ax
+	mov gs, ax
+
+	call isr_handler
+
+	pop eax
+	mov ds, ax
+	mov es, ax
+	mov fs, ax
+	mov gs, ax
+
+	popa
+	add esp, 8 					; Passed arguments
+	sti
+	iret						; Return from interrupt
diff --git a/src/interrupts.c b/src/interrupts.c
new file mode 100644
index 0000000..615f367
--- /dev/null
+++ b/src/interrupts.c
@@ -0,0 +1,15 @@
+#include "kint.h"
+#include "vga.h"
+
+struct registers
+{
+	uint ds;
+	uint edi, esi, ebp, esp, ebx, edx, ecx, eax;
+	uint interrupt_number, error_code;
+	uint eip, cs, eflags, useresp, ss;
+};
+
+void isr_handler(struct registers regs)
+{
+	vga_write("Interrupt triggered\n");
+}
diff --git a/src/kint.h b/src/kint.h
new file mode 100644
index 0000000..5b363aa
--- /dev/null
+++ b/src/kint.h
@@ -0,0 +1,8 @@
+#pragma once
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+typedef unsigned long long size_t;
diff --git a/src/link.ld b/src/link.ld
new file mode 100644
index 0000000..2abbaeb
--- /dev/null
+++ b/src/link.ld
@@ -0,0 +1,27 @@
+ENTRY(start)
+SECTIONS
+{
+    .text 0x100000 :
+    {
+        code = .; _code = .; __code = .;
+        *(.text)
+        . = ALIGN(4096);
+    }
+
+    .data :
+    {
+        data = .; _data = .; __data = .;
+        *(.data)
+        *(.rodata)
+        . = ALIGN(4096);
+    }
+
+    .bss :
+    {
+        bss = .; _bss = .; __bss = .;
+        *(.bss)
+        . = ALIGN(4096);
+    }
+
+    end = .; _end = .; __end = .;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..4854924
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,19 @@
+#include "vga.h"
+#include "descriptor_tables.h"
+
+int main(void *mboot)
+{
+	vga_clear();
+	vga_set_color(LIGHT_BLUE, BLACK);
+	vga_write("Hello!\nWelcome to Bluejay OS\n");
+
+	vga_set_color(WHITE, BLACK);
+
+	init_idt();
+
+	//init_descriptor_tables();
+
+	//asm volatile("int $0x03");
+	
+	return 0xCAFEBABE;
+}
diff --git a/src/mem.c b/src/mem.c
new file mode 100644
index 0000000..21afb34
--- /dev/null
+++ b/src/mem.c
@@ -0,0 +1,37 @@
+#include "mem.h"
+
+
+void outb(ushort port, uchar val)
+{
+	asm volatile("outb %1, %0" : : "dN" (port), "a" (val));
+}
+
+uchar inb(ushort port)
+{
+	uchar ret;
+	asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port));
+	return ret;
+}
+
+ushort inw(ushort port)
+{
+	ushort ret;
+	asm volatile("inw %1, %0" : "=a" (ret) : "dN" (port));
+	return ret;
+}
+
+void *memset(void *s, int c, size_t n)
+{
+	for (size_t i = 0; i < n; i++)
+	{
+		((uchar *)s)[i] = c;
+	}
+}
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	for (size_t i = 0; i < n; i++)
+	{
+		((uchar *)dest)[i] = ((uchar *)src)[i];
+	}
+}
diff --git a/src/mem.h b/src/mem.h
new file mode 100644
index 0000000..b55eb8b
--- /dev/null
+++ b/src/mem.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "kint.h"
+
+void outb(ushort port, uchar val);
+uchar inb(ushort port);
+ushort inw(ushort port);
+
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *dest, const void *src, size_t n);
diff --git a/src/vga.c b/src/vga.c
new file mode 100644
index 0000000..1b10833
--- /dev/null
+++ b/src/vga.c
@@ -0,0 +1,111 @@
+#include "vga.h"
+#include "mem.h"
+
+static uint cursor_x = 0;
+static uint cursor_y = 0;
+
+static ushort color = WHITE;
+
+static ushort *fb = (ushort *)0xB8000;
+
+static void move_cursor()
+{
+	ushort loc = cursor_y * 80 + cursor_x;
+	outb(0x3d4, 14); // Setting high cursor byte
+	outb(0x3d4, loc >> 8);
+
+	outb(0x3d4, 15); // low byte
+	outb(0x3d4, loc & 0xff);
+}
+
+static void scroll()
+{
+	ushort blank = ' ' | color << 8;
+
+	while (cursor_y >= 25) // end of line
+	{
+		// scroll everything up
+		memcpy(fb, &fb[80], 24 * 80 * 2);
+
+		for (int i = 24 * 80; i < 25 * 80; i++)
+		{
+			fb[i] = blank;
+		}
+
+		cursor_y--;
+	}
+}
+
+void vga_set_color(enum vga_colors fg, enum vga_colors bg)
+{
+	color = (bg << 4) | fg & 0xf;
+}
+
+void vga_put(char c)
+{
+	switch (c)
+	{
+	case '\b':
+		if (cursor_x > 0)
+			cursor_x--;
+		break;
+	case '\t':
+		cursor_x = (cursor_x + 8) & ~ 7;
+		break;
+	case '\n':
+		cursor_y++;
+	case '\r':
+		cursor_x = 0;
+		break;
+	default:
+		cursor_x++;
+		fb[cursor_y * 80 + cursor_x] = c | (color << 8);
+	}
+
+	if (cursor_x >= 80) // off screen
+	{
+		cursor_x = 0;
+		cursor_y++;
+	}
+
+	scroll();
+	move_cursor();
+}
+
+void vga_clear()
+{
+	memset(fb, 0, 80 * 25 * 2);
+	cursor_x = 0;
+	cursor_y = 0;
+	move_cursor();
+}
+
+void vga_write(char *c)
+{
+	for (int i = 0; c[i]; i++)
+		vga_put(c[i]);
+}
+
+void vga_putd(uint d)
+{
+	
+}
+
+static void vga_put_nibble(uchar n)
+{
+	if (n <= 9)
+		vga_put('0' + n);
+	else
+		vga_put('A' + n - 10);
+}
+
+void vga_putx(uint x)
+{
+	for (uint mask = 0xFF000000, shift = 24; mask; mask >>= 8, shift -= 8)
+	{
+		uchar byte = (x & mask) >> shift;
+
+		vga_put_nibble((byte & 0xf0) >> 8);
+		vga_put_nibble(byte & 0x0f);
+	}
+}
diff --git a/src/vga.h b/src/vga.h
new file mode 100644
index 0000000..0968ca1
--- /dev/null
+++ b/src/vga.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "kint.h"
+
+enum vga_colors
+{
+	BLACK = 0,
+	BLUE,
+	GREEN,
+	CYAN,
+	RED,
+	MAGENTA,
+	BROWN,
+	LIGHT_GREY,
+	DARK_GREY,
+	LIGHT_BLUE,
+	LIGHT_GREEN,
+	LIGHT_CYAN,
+	LIGHT_RED,
+	LIGHT_MAGENTA,
+	LIGHT_BROWN,
+	WHITE,
+};
+
+void vga_set_color(enum vga_colors fg, enum vga_colors bg);
+void vga_put(char c);
+void vga_putx(uint x);
+void vga_clear();
+void vga_write(char *c);