Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a931712
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.iso
+*.elf
+*.bin
+*.o
+*.a
+*.so
\ No newline at end of file
diff --git a/bin/bin.txt b/bin/bin.txt
new file mode 100644
index 0000000..9996874
--- /dev/null
+++ b/bin/bin.txt
@@ -0,0 +1,2 @@
+This directory holds system and user binaries.
+Bluejay.iso will be built here.
diff --git a/boot/grub/grub.cfg b/boot/grub/grub.cfg
new file mode 100644
index 0000000..6d93ca4
--- /dev/null
+++ b/boot/grub/grub.cfg
@@ -0,0 +1,3 @@
+menuentry "Bluejay" {
+ multiboot /boot/kernel.elf
+}
\ No newline at end of file
diff --git a/doc/building.txt b/doc/building.txt
new file mode 100644
index 0000000..e25de1b
--- /dev/null
+++ b/doc/building.txt
@@ -0,0 +1,4 @@
+Building Bluejay
+----------------
+
+From the /src/ directory run `make', a bootable .iso file will be built into /bin
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);