aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/global_descriptor_table.c50
-rw-r--r--kernel/global_descriptor_table.h1
-rw-r--r--kernel/interrupt_descriptor_table.h8
-rw-r--r--kernel/io/keyboard/keyboard_handler.c73
-rw-r--r--kernel/io/keyboard/keyboard_handler.h1
-rw-r--r--kernel/io/keyboard/scancode_map.h93
-rw-r--r--kernel/io/vga/text_mode_diplay.h4
-rw-r--r--kernel/io/vga/text_mode_display.c6
-rw-r--r--kernel/io/vga/text_mode_display.h5
-rw-r--r--kernel/kernel-bootstrap.asm45
-rw-r--r--kernel/kernel.c7
11 files changed, 286 insertions, 7 deletions
diff --git a/kernel/global_descriptor_table.c b/kernel/global_descriptor_table.c
new file mode 100644
index 0000000..16b99dc
--- /dev/null
+++ b/kernel/global_descriptor_table.c
@@ -0,0 +1,50 @@
+extern void flush_gdt();
+
+struct gdt_entry
+{
+ unsigned short limit_low;
+ unsigned short base_low;
+ unsigned char base_middle;
+ unsigned char access;
+ unsigned char granularity;
+ unsigned char base_high;
+} __attribute__((packed));
+
+struct gdt_ptr
+{
+ unsigned short limit;
+ unsigned int base;
+} __attribute__((packed));
+
+struct gdt_entry gdt[3];
+struct gdt_ptr gdt_pointer;
+
+void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
+{
+
+ gdt[num].base_low = (base & 0xFFFF);
+ gdt[num].base_middle = (base >> 16) & 0xFF;
+ gdt[num].base_high = (base >> 24) & 0xFF;
+
+ gdt[num].limit_low = (limit & 0xFFFF);
+ gdt[num].granularity = ((limit >> 16) & 0x0F);
+
+ gdt[num].granularity |= (gran & 0xF0);
+ gdt[num].access = access;
+}
+
+void init_gdt()
+{
+ gdt_pointer.limit = (sizeof(struct gdt_entry) * 3) - 1;
+ gdt_pointer.base = (unsigned int) &gdt;
+
+ // Values taken from bkerndev
+ // First GDT segment must be null
+ gdt_set_gate(0, 0, 0, 0, 0);
+ // Code segment
+ gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
+ // Data segment
+ gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+
+ flush_gdt();
+} \ No newline at end of file
diff --git a/kernel/global_descriptor_table.h b/kernel/global_descriptor_table.h
new file mode 100644
index 0000000..2774cb1
--- /dev/null
+++ b/kernel/global_descriptor_table.h
@@ -0,0 +1 @@
+void init_gdt(); \ No newline at end of file
diff --git a/kernel/interrupt_descriptor_table.h b/kernel/interrupt_descriptor_table.h
new file mode 100644
index 0000000..1d0216b
--- /dev/null
+++ b/kernel/interrupt_descriptor_table.h
@@ -0,0 +1,8 @@
+struct idt_entry
+{
+ unsigned short int offset_lowerbits;
+ unsigned short int selector;
+ unsigned char zero;
+ unsigned char type_attr;
+ unsigned short int offset_higherbits;
+} __attribute__((packed)); \ No newline at end of file
diff --git a/kernel/io/keyboard/keyboard_handler.c b/kernel/io/keyboard/keyboard_handler.c
new file mode 100644
index 0000000..86a50a7
--- /dev/null
+++ b/kernel/io/keyboard/keyboard_handler.c
@@ -0,0 +1,73 @@
+#include "../../interrupt_descriptor_table.h"
+#include "../vga/text_mode_display.h"
+#include "scancode_map.h"
+
+extern void keyboard_handler(void);
+extern char read_port(unsigned short port);
+extern void write_port(unsigned short port, unsigned char data);
+extern void load_idt(unsigned long *idt_ptr);
+
+struct idt_entry keyboard_idt[256];
+
+void init_keyboard_idt()
+{
+ unsigned long keyboard_address;
+ unsigned long idt_address;
+ unsigned long idt_ptr[2];
+
+ // Build IDT entry
+ keyboard_address = (unsigned long) keyboard_handler;
+
+ keyboard_idt[0x21].offset_lowerbits = keyboard_address & 0xffff;
+ keyboard_idt[0x21].selector = 0x08; // Offset by 0x08
+ keyboard_idt[0x21].zero = 0;
+ keyboard_idt[0x21].type_attr = 0x8E; // Interrupt gate addr
+ keyboard_idt[0x21].offset_higherbits = (keyboard_address & 0xffff0000) >> 16;
+
+ idt_address = (unsigned long) keyboard_idt;
+ idt_ptr[0] = (sizeof(struct idt_entry) * 256) + ((idt_address & 0xffff) << 16);
+ idt_ptr[1] = idt_address >> 16;
+
+ // Init PIC 1 @ 0x20
+ write_port(0x20, 0x11);
+ write_port(0x21, 0x20);
+ write_port(0x21, 0x00);
+ write_port(0x21, 0x01);
+ write_port(0x21, 0xff);
+
+ // PIC 2 @ 0xA0
+ write_port(0xA0, 0x11);
+ write_port(0xA1, 0x28);
+ write_port(0xA1, 0x00);
+ write_port(0xA1, 0x01);
+ write_port(0xA1, 0xff);
+
+ load_idt(idt_ptr);
+}
+
+void init_keyboard_handler()
+{
+ init_keyboard_idt();
+
+ write_port(0x21, 0xFD);
+}
+
+int isKeyup(int scancode)
+{
+ return scancode & 0x80;
+}
+
+void handle_keypress() {
+
+ // Ack the interrupt
+ write_port(0x20, 0x20);
+
+ unsigned char scancode = read_port(0x60);
+
+ if(!isKeyup(scancode))
+ {
+ char pressed_key = scancode_map[scancode];
+ vga_print_raw(pressed_key);
+ }
+
+}
diff --git a/kernel/io/keyboard/keyboard_handler.h b/kernel/io/keyboard/keyboard_handler.h
new file mode 100644
index 0000000..f56f4f2
--- /dev/null
+++ b/kernel/io/keyboard/keyboard_handler.h
@@ -0,0 +1 @@
+void init_keyboard_handler(); \ No newline at end of file
diff --git a/kernel/io/keyboard/scancode_map.h b/kernel/io/keyboard/scancode_map.h
new file mode 100644
index 0000000..e48a1f6
--- /dev/null
+++ b/kernel/io/keyboard/scancode_map.h
@@ -0,0 +1,93 @@
+char scancode_map[128] =
+{
+ 0xFF, // Keyboard error code
+ 0, // Esc
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ '0',
+ '-',
+ '=',
+ '\b', // Backspace
+ '\t', // Tab
+ 'q',
+ 'w',
+ 'e',
+ 'r',
+ 't',
+ 'y',
+ 'u',
+ 'i',
+ 'o',
+ 'p',
+ '[',
+ ']',
+ '\n', // Enter
+ 0, // Ctrl
+ 'a',
+ 's',
+ 'd',
+ 'f',
+ 'g',
+ 'h',
+ 'j',
+ 'k',
+ 'l',
+ ';',
+ '\'',
+ '`',
+ 0, // Left Shift
+ '\\',
+ 'z',
+ 'x',
+ 'c',
+ 'v',
+ 'b',
+ 'n',
+ 'm',
+ ',',
+ '.',
+ '/',
+ 0, // Right shift
+ '*',
+ 0, // Alt
+ ' ', // Space
+ 0, // Caps
+ 0, // F1 ...
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, // F10
+ 0, // Numlock
+ 0, // Scroll lock
+ 0, // Home
+ 0, // Up
+ 0, // PgUp
+ '-',
+ 0, // Left
+ 0, // Numpad 5
+ 0, // Right
+ '+',
+ 0, // End
+ 0, // Down
+ 0, // PgDown
+ 0, // Ins
+ 0, // Del
+ 0, // Alt-Sysrq
+ 0, // n/a
+ 0, // n/a
+ 0, // F11
+ 0, // F12
+ 0, // Others are undefined
+}; \ No newline at end of file
diff --git a/kernel/io/vga/text_mode_diplay.h b/kernel/io/vga/text_mode_diplay.h
deleted file mode 100644
index 9441925..0000000
--- a/kernel/io/vga/text_mode_diplay.h
+++ /dev/null
@@ -1,4 +0,0 @@
-void vga_clear_screen();
-void vga_print(char *msg);
-void vga_print_ln(char *msg);
-void vga_set_text_colour(int foreground, int background); \ No newline at end of file
diff --git a/kernel/io/vga/text_mode_display.c b/kernel/io/vga/text_mode_display.c
index 4844524..bfee909 100644
--- a/kernel/io/vga/text_mode_display.c
+++ b/kernel/io/vga/text_mode_display.c
@@ -39,4 +39,10 @@ void vga_print_ln(char *msg)
void vga_set_text_colour(int foreground, int background)
{
char_attribute_byte = (background << 4) | foreground;
+}
+
+void vga_print_raw(unsigned char byte)
+{
+ video_ram[cursor_pos++] = byte;
+ video_ram[cursor_pos++] = char_attribute_byte;
} \ No newline at end of file
diff --git a/kernel/io/vga/text_mode_display.h b/kernel/io/vga/text_mode_display.h
new file mode 100644
index 0000000..48bae85
--- /dev/null
+++ b/kernel/io/vga/text_mode_display.h
@@ -0,0 +1,5 @@
+void vga_clear_screen();
+void vga_print(char *msg);
+void vga_print_ln(char *msg);
+void vga_set_text_colour(int foreground, int background);
+void vga_print_raw(unsigned char byte); \ No newline at end of file
diff --git a/kernel/kernel-bootstrap.asm b/kernel/kernel-bootstrap.asm
index 9e3b10e..8af3565 100644
--- a/kernel/kernel-bootstrap.asm
+++ b/kernel/kernel-bootstrap.asm
@@ -7,12 +7,53 @@ dd 0x1BADB002
dd 0x00
dd - (0x1BADB002 + 0x00) ; checksum
+global flush_gdt
+global read_port
+global write_port
+global load_idt
+global keyboard_handler
global start
+
extern kernel_entrypoint
+extern handle_keypress
+extern gdt_pointer
+
+flush_gdt:
+ lgdt [gdt_pointer]
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ jmp 0x08:flush
+flush:
+ ret
+
+read_port:
+ mov edx, [esp + 4]
+ in al, dx
+ ret
+
+write_port:
+ mov edx, [esp + 4]
+ mov al, [esp + 4 + 4]
+ out dx, al
+ ret
+
+load_idt:
+ mov edx, [esp + 4]
+ lidt [edx]
+ sti
+ ret
+
+keyboard_handler:
+ call handle_keypress
+ iretd
+
- ; call kernel and halt
start:
- cli ; disable interrups
+ cli
mov esp, stack_space
call kernel_entrypoint
hlt
diff --git a/kernel/kernel.c b/kernel/kernel.c
index fa659dc..ab518e6 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -1,5 +1,7 @@
-#include "./io/vga/text_mode_diplay.h"
+#include "./io/vga/text_mode_display.h"
#include "./io/vga/colours.h"
+#include "./io/keyboard/keyboard_handler.h"
+#include "global_descriptor_table.h"
void run_kern_demo()
{
@@ -92,5 +94,8 @@ void run_kern_demo()
void kernel_entrypoint()
{
+ init_gdt();
+ init_keyboard_handler();
run_kern_demo();
+ while(1);
}