aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2024-02-06 04:58:35 -0600
committerNic Gaffney <gaffney_nic@protonmail.com>2024-02-06 04:58:35 -0600
commitecf636f2797647d5dfc38a4562cae53fe275217d (patch)
treec71d113c553821c2b949eb6a6cd67de5f2fce068 /src/kernel
parentf1dee4bc58e4bfb97a1b41831c5d4fc327882991 (diff)
downloadgftos-ecf636f2797647d5dfc38a4562cae53fe275217d.tar.gz
Interrupts + basic keyboard driver
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/exceptions.c9
-rw-r--r--src/kernel/idt.c23
-rw-r--r--src/kernel/kernel.c55
-rw-r--r--src/kernel/keyboard/compile_flags.txt1
-rw-r--r--src/kernel/keyboard/isr.c49
-rw-r--r--src/kernel/keyboard/isr_wrap.s8
-rw-r--r--src/kernel/keyboard/pic.c65
-rw-r--r--src/kernel/print.c32
-rw-r--r--src/kernel/stub_table.asm33
-rw-r--r--src/kernel/tables/compile_flags.txt1
-rw-r--r--src/kernel/tables/gdt.c (renamed from src/kernel/gdt.c)4
-rw-r--r--src/kernel/tables/idt.c27
-rw-r--r--src/kernel/tables/stub.s53
13 files changed, 260 insertions, 100 deletions
diff --git a/src/kernel/exceptions.c b/src/kernel/exceptions.c
new file mode 100644
index 0000000..ded9e9b
--- /dev/null
+++ b/src/kernel/exceptions.c
@@ -0,0 +1,9 @@
+#include "print.h"
+
+__attribute__((noreturn)) void exception_handler(void);
+void exception_handler() {
+ print_set_color(PRINT_COLOR_RED, PRINT_COLOR_BLACK);
+ print_clear();
+ printf("KERNEL EXCEPTION");
+ __asm__ volatile("cli; hlt");
+}
diff --git a/src/kernel/idt.c b/src/kernel/idt.c
deleted file mode 100644
index 2805889..0000000
--- a/src/kernel/idt.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "idt.h"
-#include "gdt.h"
-#include <stdint.h>
-
-static Gate_Descriptor_t idt[256];
-extern GDTR_t idtr;
-
-void get_idtr() {
- idtr.offset = (uintptr_t)&idt[0];
- idtr.size = sizeof(Gate_Descriptor_t) * 256 - 1;
- for (uint8_t vec = 0; vec < 32; vec++) {
- make_gate(stub_table[vec], 0x8E, vec);
- }
-}
-
-void make_gate(uint32_t offset, uint8_t attrs, uint8_t vec) {
- Gate_Descriptor_t *descriptor = &idt[vec];
-
- descriptor->offset_low = offset & 0xFFFF;
- descriptor->attrs = (0b1000 << 4) | attrs;
- descriptor->offset_high = offset >> 16, descriptor->segment_selector = 0x08;
- descriptor->reserved = 0;
-}
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index b582e85..7dd3deb 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -1,5 +1,9 @@
-#include "kernel.h"
+#include "asm.h"
+#include "gdt.h"
+#include "isr.h"
#include "print.h"
+extern GDTR_t idtr;
+extern GDTR_t gdtr;
#if defined(__linux__)
#error "Not using cross compiler!"
@@ -10,49 +14,20 @@
#error "Must use ix86-elf compiler"
#endif
-void motd() {
- char *empty_row = " "
- " \n";
- empty_row[0] = (char)186;
- empty_row[79] = (char)186;
-
- printf("%c", 201);
- for (int i = 0; i < 78; i++)
- printf("%c", 205);
- printf("%c\n", 187);
-
- printf(empty_row);
-
- printf("%c", 186);
- for (int i = 0; i < 78 / 2 - 17 / 2; i++)
- printf(" ");
- printf("Welcome to gftos!");
- for (int i = 0; i < 78 / 2 - 17 / 2 - 1; i++)
- printf(" ");
- printf("%c\n", 186);
-
- for (int i = 0; i < 21; i++) {
- printf(empty_row);
- }
-
- printf("%c", 200);
- for (int i = 0; i < 78; i++)
- printf("%c", 205);
- printf("%c", 188);
-}
-
-void kernel_panic(const char *error) {
- print_set_color(PRINT_COLOR_BLACK, PRINT_COLOR_RED);
- print_clear();
- printf(" PANIC! ERROR: %s", error);
- for (;;)
- ;
-}
+void motd() { printf("Welcome to gftos!\n=================\n"); }
void kernel_main(void) {
+ PIC_init(0x20, 0xA0);
+ IRQ_mask(0);
+
+ print_set_color(PRINT_COLOR_PINK, PRINT_COLOR_DARK_GRAY);
print_clear();
motd();
- /* kernel_panic("test_panic."); */
+ for (;;) {
+ update_cursor();
+ asm("hlt");
+ }
+
// for (int r = 0; r < 24; r++) {
// for (int c = 0; c < 80; c += 3) {
// int color = (r + c) % 15 + 1;
diff --git a/src/kernel/keyboard/compile_flags.txt b/src/kernel/keyboard/compile_flags.txt
new file mode 100644
index 0000000..2af49c7
--- /dev/null
+++ b/src/kernel/keyboard/compile_flags.txt
@@ -0,0 +1 @@
+-I../../include/
diff --git a/src/kernel/keyboard/isr.c b/src/kernel/keyboard/isr.c
new file mode 100644
index 0000000..223bf9f
--- /dev/null
+++ b/src/kernel/keyboard/isr.c
@@ -0,0 +1,49 @@
+#include "asm.h"
+#include "print.h"
+#include "str.h"
+#include <stdint.h>
+static uint8_t shift_held = 0;
+static uint8_t capslock = 0;
+
+void keyboard_handler() {
+ const char *scancodes =
+ "??1234567890-=?\tqwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ";
+ const char *SCANCODES =
+ "\?\?!@#$%^&*()_+?\tQWERTYUIOP{}\n?ASDFGHJKL:\"~?|ZXCVBNM<>??*? ";
+
+ unsigned char sc = inb(0x60);
+
+ uint8_t isheld = shift_held != 0;
+ char c = ((isheld | capslock) & !(isheld & capslock)) ? SCANCODES[sc]
+ : scancodes[sc];
+
+ if (capslock & (!isheld) && !isalpha(c))
+ c = scancodes[sc];
+ if (isheld && !isalpha(c))
+ c = SCANCODES[sc];
+
+ if (sc < 0x59 && scancodes[sc] != '?')
+ printf("%c", c);
+
+ switch (sc) {
+ case 0x2A:
+ shift_held |= 0b10;
+ break;
+ case 0x36:
+ shift_held |= 0b01;
+ break;
+ case 0xAA:
+ shift_held &= 0b01;
+ break;
+ case 0xB6:
+ shift_held &= 0b10;
+ break;
+ case 0x0E:
+ delete_char();
+ break;
+ case 0x3A:
+ capslock = !capslock;
+ break;
+ }
+ outb(0x20, 0x20);
+}
diff --git a/src/kernel/keyboard/isr_wrap.s b/src/kernel/keyboard/isr_wrap.s
new file mode 100644
index 0000000..6f6c58b
--- /dev/null
+++ b/src/kernel/keyboard/isr_wrap.s
@@ -0,0 +1,8 @@
+extern keyboard_handler
+extern wrap_keyboard_handler
+wrap_keyboard_handler:
+ pushad
+ cld
+ call keyboard_handler
+ popad
+ iret
diff --git a/src/kernel/keyboard/pic.c b/src/kernel/keyboard/pic.c
index 0c81629..e1b4fb3 100644
--- a/src/kernel/keyboard/pic.c
+++ b/src/kernel/keyboard/pic.c
@@ -1 +1,66 @@
#include "asm.h"
+#include <stdint.h>
+#define PIC1 0x20
+#define PIC2 0xA0
+#define PIC1_COMMAND PIC1
+#define PIC1_DATA (PIC1 + 1)
+#define PIC2_COMMAND PIC2
+#define PIC2_DATA (PIC2 + 1)
+
+void PIC_init(int offset1, int offset2) {
+ uint8_t a1, a2;
+
+ a1 = inb(PIC1_DATA);
+ a2 = inb(PIC2_DATA);
+
+ outb(PIC1_COMMAND, 0x11); // Init PIC1
+ io_wait();
+ outb(PIC2_COMMAND, 0x11); // Init PIC2
+ io_wait();
+ outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
+ io_wait();
+ outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
+ io_wait();
+ outb(PIC1_DATA, 4);
+ io_wait();
+ outb(PIC2_DATA, 2);
+ io_wait();
+ outb(PIC1_DATA, 0x01);
+ io_wait();
+ outb(PIC2_DATA, 0x01);
+ io_wait();
+
+ outb(PIC1_DATA, a1); // restore saved masks.
+ outb(PIC2_DATA, a2);
+}
+
+void IRQ_mask(uint8_t line) {
+ uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA;
+ line = line > 8 ? line - 8 : line;
+ uint8_t val = inb(port) | (1 << line);
+ outb(port, val);
+}
+
+void IRQ_unmask(uint8_t line) {
+ uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA;
+ line = line > 8 ? line - 8 : line;
+ uint8_t val = inb(port) & ~(1 << line);
+ outb(port, val);
+}
+
+void PIC_disable(void) {
+ outb(PIC1_DATA, 0xff);
+ outb(PIC2_DATA, 0xff);
+}
+
+uint16_t PIC_irr(void) {
+ outb(PIC1_COMMAND, 0x0a);
+ outb(PIC2_COMMAND, 0x0a);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}
+
+uint16_t PIC_isr(void) {
+ outb(PIC1_COMMAND, 0x0b);
+ outb(PIC2_COMMAND, 0x0b);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}
diff --git a/src/kernel/print.c b/src/kernel/print.c
index d5e8790..7a54c7b 100644
--- a/src/kernel/print.c
+++ b/src/kernel/print.c
@@ -1,9 +1,12 @@
#include "print.h"
+#include "asm.h"
#include "str.h"
#include <stdarg.h>
+#include <stdint.h>
// Constants
static const size_t NUM_COLS = 80;
static const size_t NUM_ROWS = 25;
+static uint8_t cursor = 0;
// Char struct
struct Char {
@@ -34,6 +37,18 @@ void clear_row(size_t row) {
}
}
+void delete_char() {
+ if (col == 0) {
+ row--;
+ col = NUM_COLS;
+ }
+ col--;
+ buffer[col + NUM_COLS * row] = (struct Char){
+ ' ',
+ color,
+ };
+}
+
// Call clear_row for every row
void print_clear() {
for (size_t i = 0; i < NUM_ROWS; i++) {
@@ -62,6 +77,15 @@ void print_newline() {
clear_row(NUM_ROWS - 1);
}
+void update_cursor() {
+ uint16_t pos = col + NUM_COLS * row;
+
+ outb(0x3D4, 0x0F);
+ outb(0x3D5, (uint8_t)(pos & 0xFF));
+ outb(0x3D4, 0x0E);
+ outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
+}
+
// printchar
void print_char(char character) {
// If \n, call newline
@@ -76,7 +100,7 @@ void print_char(char character) {
}
// if cols is too large, overflow
- if (col > NUM_COLS) {
+ if (col >= NUM_COLS) {
print_newline();
}
@@ -105,7 +129,7 @@ void print_set_color(uint8_t foreground, uint8_t background) {
void printf(const char *str, ...) {
va_list args;
va_start(args, str);
- char temp_str[256];
+ char temp_str[256] = "";
for (size_t i = 0; str[i] != '\0'; ++i) {
if (str[i] == '%') {
@@ -114,6 +138,10 @@ void printf(const char *str, ...) {
case 'd':
print_str(itoa(va_arg(args, int), temp_str, 10));
break;
+ case 'x':
+ print_str("0x");
+ print_str(itoa(va_arg(args, int), temp_str, 16));
+ break;
case 's':
print_str(va_arg(args, char *));
break;
diff --git a/src/kernel/stub_table.asm b/src/kernel/stub_table.asm
deleted file mode 100644
index 9901cea..0000000
--- a/src/kernel/stub_table.asm
+++ /dev/null
@@ -1,33 +0,0 @@
-extern exception_handler
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_err_stub 0
-isr_no_err_stub 0
-isr_err_stub 0
-isr_err_stub 0
-isr_err_stub 0
-isr_err_stub 0
-isr_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_no_err_stub 0
-isr_err_stub 0
-isr_no_err_stub 0
diff --git a/src/kernel/tables/compile_flags.txt b/src/kernel/tables/compile_flags.txt
new file mode 100644
index 0000000..2af49c7
--- /dev/null
+++ b/src/kernel/tables/compile_flags.txt
@@ -0,0 +1 @@
+-I../../include/
diff --git a/src/kernel/gdt.c b/src/kernel/tables/gdt.c
index 406b40c..9c65152 100644
--- a/src/kernel/gdt.c
+++ b/src/kernel/tables/gdt.c
@@ -4,9 +4,9 @@
GDT_t table = 0x0;
extern GDTR_t gdtr;
void get_gdtr() {
- uint32_t base = 0x0000;
+ uint32_t base = (uint32_t)table;
- table[0] = make_descriptor(0, 0, 0);
+ table[0] = make_descriptor(base, 0, 0);
table[1] = make_descriptor(base, 0x3FFFF, make_code(0, 0, 1));
table[2] = make_descriptor(base, 0x3FFFF, make_data(0, 0, 1));
diff --git a/src/kernel/tables/idt.c b/src/kernel/tables/idt.c
new file mode 100644
index 0000000..01a6776
--- /dev/null
+++ b/src/kernel/tables/idt.c
@@ -0,0 +1,27 @@
+#include "idt.h"
+#include "gdt.h"
+#include "isr.h"
+#include <stdint.h>
+
+__attribute__((aligned(0x10))) static Gate_Descriptor_t idt[256];
+extern GDTR_t idtr;
+extern void *isr_stub_table;
+
+void get_idtr() {
+ idtr.offset = (uintptr_t)&idt[0];
+ idtr.size = sizeof(Gate_Descriptor_t) * 256 - 1;
+ for (uint8_t vec = 0; vec < 32; vec++) {
+ make_gate(((void **)(isr_stub_table))[vec], 0x8E, vec);
+ }
+ make_gate(wrap_keyboard_handler, 0x8E, 0x21);
+}
+
+void make_gate(void *isr, uint8_t attrs, uint8_t vec) {
+ Gate_Descriptor_t *descriptor = &idt[vec];
+
+ descriptor->offset_low = (uint32_t)isr & 0xFFFF;
+ descriptor->attrs = (0b1000 << 4) | attrs;
+ descriptor->offset_high = (uint32_t)isr >> 16;
+ descriptor->segment_selector = 0x08;
+ descriptor->reserved = 0;
+}
diff --git a/src/kernel/tables/stub.s b/src/kernel/tables/stub.s
new file mode 100644
index 0000000..11e457a
--- /dev/null
+++ b/src/kernel/tables/stub.s
@@ -0,0 +1,53 @@
+
+%macro isr_err_stub 1
+isr_stub_%+%1:
+ call exception_handler
+ iret
+%endmacro
+%macro isr_no_err_stub 1
+isr_stub_%+%1:
+ call exception_handler
+ iret
+%endmacro
+
+extern exception_handler
+isr_no_err_stub 0
+isr_no_err_stub 1
+isr_no_err_stub 2
+isr_no_err_stub 3
+isr_no_err_stub 4
+isr_no_err_stub 5
+isr_no_err_stub 6
+isr_no_err_stub 7
+isr_err_stub 8
+isr_no_err_stub 9
+isr_err_stub 10
+isr_err_stub 11
+isr_err_stub 12
+isr_err_stub 13
+isr_err_stub 14
+isr_no_err_stub 15
+isr_no_err_stub 16
+isr_err_stub 17
+isr_no_err_stub 18
+isr_no_err_stub 19
+isr_no_err_stub 20
+isr_no_err_stub 21
+isr_no_err_stub 22
+isr_no_err_stub 23
+isr_no_err_stub 24
+isr_no_err_stub 25
+isr_no_err_stub 26
+isr_no_err_stub 27
+isr_no_err_stub 28
+isr_no_err_stub 29
+isr_err_stub 30
+isr_no_err_stub 31
+
+global isr_stub_table
+isr_stub_table:
+%assign i 0
+%rep 32
+ dd isr_stub_%+i
+%assign i i+1
+%endrep