diff options
| author | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-02-06 04:58:35 -0600 |
|---|---|---|
| committer | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-02-06 04:58:35 -0600 |
| commit | ecf636f2797647d5dfc38a4562cae53fe275217d (patch) | |
| tree | c71d113c553821c2b949eb6a6cd67de5f2fce068 /src | |
| parent | f1dee4bc58e4bfb97a1b41831c5d4fc327882991 (diff) | |
| download | gftos-ecf636f2797647d5dfc38a4562cae53fe275217d.tar.gz | |
Interrupts + basic keyboard driver
Diffstat (limited to 'src')
| -rw-r--r-- | src/boot/boot.s | 4 | ||||
| -rw-r--r-- | src/include/gdt.h | 6 | ||||
| -rw-r--r-- | src/include/idt.h | 2 | ||||
| -rw-r--r-- | src/include/isr.h | 10 | ||||
| -rw-r--r-- | src/include/print.h | 2 | ||||
| -rw-r--r-- | src/include/str.h | 1 | ||||
| -rw-r--r-- | src/kernel/exceptions.c | 9 | ||||
| -rw-r--r-- | src/kernel/idt.c | 23 | ||||
| -rw-r--r-- | src/kernel/kernel.c | 55 | ||||
| -rw-r--r-- | src/kernel/keyboard/compile_flags.txt | 1 | ||||
| -rw-r--r-- | src/kernel/keyboard/isr.c | 49 | ||||
| -rw-r--r-- | src/kernel/keyboard/isr_wrap.s | 8 | ||||
| -rw-r--r-- | src/kernel/keyboard/pic.c | 65 | ||||
| -rw-r--r-- | src/kernel/print.c | 32 | ||||
| -rw-r--r-- | src/kernel/stub_table.asm | 33 | ||||
| -rw-r--r-- | src/kernel/tables/compile_flags.txt | 1 | ||||
| -rw-r--r-- | src/kernel/tables/gdt.c (renamed from src/kernel/gdt.c) | 4 | ||||
| -rw-r--r-- | src/kernel/tables/idt.c | 27 | ||||
| -rw-r--r-- | src/kernel/tables/stub.s | 53 | ||||
| -rw-r--r-- | src/utils/str.c | 12 |
20 files changed, 286 insertions, 111 deletions
diff --git a/src/boot/boot.s b/src/boot/boot.s index 8df5c6b..dbb4052 100644 --- a/src/boot/boot.s +++ b/src/boot/boot.s @@ -48,13 +48,13 @@ _start: call get_idtr lidt [idtr] sti + xchg bx, bx [bits 32] extern kernel_main call kernel_main - ; BOCHS - xchg bx, bx + cli diff --git a/src/include/gdt.h b/src/include/gdt.h index 8cc2542..b8d219a 100644 --- a/src/include/gdt.h +++ b/src/include/gdt.h @@ -16,12 +16,6 @@ typedef struct GDTR { uint32_t offset; } __attribute__((packed)) GDTR_t; -// typedef struct GDT { -// Segment_Descriptor_t nulldesc; -// Segment_Descriptor_t codedesc; -// Segment_Descriptor_t datadesc; -// } __attribute__((packed)) GDT_t; - typedef Segment_Descriptor_t *GDT_t; uint16_t make_code(uint8_t priv, uint8_t dc, uint8_t rw); diff --git a/src/include/idt.h b/src/include/idt.h index 78d736b..4724042 100644 --- a/src/include/idt.h +++ b/src/include/idt.h @@ -9,6 +9,6 @@ typedef struct Gate_Descriptor { uint16_t offset_high; } __attribute__((packed)) Gate_Descriptor_t; -void make_gate(uint32_t offset, uint8_t attrs, uint8_t vec); +void make_gate(void *isr, uint8_t attrs, uint8_t vec); void get_idtr(); diff --git a/src/include/isr.h b/src/include/isr.h new file mode 100644 index 0000000..4380e45 --- /dev/null +++ b/src/include/isr.h @@ -0,0 +1,10 @@ +#pragma once +#include <stdint.h> +void PIC_init(int offset1, int offset2); +void PIC_disable(void); +uint16_t PIC_irr(void); +uint16_t PIC_isr(void); +void PIC_send(uint8_t irq, uint16_t cmd); +void IRQ_mask(uint8_t line); +void IRQ_unmask(uint8_t line); +void wrap_keyboard_handler(); diff --git a/src/include/print.h b/src/include/print.h index 3b94c6e..eeecfec 100644 --- a/src/include/print.h +++ b/src/include/print.h @@ -23,6 +23,8 @@ enum { }; // Prototypes +void update_cursor(); +void delete_char(); void print_clear(); void print_char(char); void print_str(char *); diff --git a/src/include/str.h b/src/include/str.h index 4e84e9c..bf7fd07 100644 --- a/src/include/str.h +++ b/src/include/str.h @@ -3,3 +3,4 @@ char *itoa(int, char *, int); size_t strlen(const char *); char *str_reverse(char *); +int isalpha(int); 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 diff --git a/src/utils/str.c b/src/utils/str.c index 9a7acb0..362f797 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -8,6 +8,8 @@ size_t strlen(const char *str) { return size; } +int isalpha(int c) { return (c > 64 && c < 91) || (c > 96 && c < 123); } + char *str_reverse(char *str) { char *str_ptr = str; size_t size = strlen(str); @@ -24,8 +26,14 @@ char *str_reverse(char *str) { char *itoa(int num, char *str, int base) { char *str_ptr = str; - for (; num;) { - *str_ptr++ = num % base + 48; + if (num == 0) + return "0"; + if (num < 0) { + *str_ptr++ = '-'; + num *= -1; + } + while (num) { + *str_ptr++ = num % base + (num % base > 9 ? 55 : 48); num /= base; } str_reverse(str); |
