From 751a18212218e8c1b6fa4ef0e464ff4c161401e1 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 23 Aug 2025 22:45:59 +0200 Subject: [PATCH] ... --- makefile | 16 +++++++- src/exceptions.c | 30 +++++++++++++++ src/idt.c | 59 ++++++++++++++++++++++++++++ src/idt.h | 3 ++ src/interrupts.asm | 96 ++++++++++++++++++++++++++++++++++++++++++++++ src/kernel.c | 10 ++++- src/keyboard.c | 80 ++++++++++++++++++++++++++++++++++++++ src/keyboard.h | 4 ++ src/print.c | 42 ++++---------------- src/print.h | 36 ++++++++++++++++- src/string.c | 10 +++++ src/string.h | 3 ++ 12 files changed, 348 insertions(+), 41 deletions(-) create mode 100644 src/exceptions.c create mode 100644 src/idt.c create mode 100644 src/idt.h create mode 100644 src/interrupts.asm create mode 100644 src/keyboard.c create mode 100644 src/keyboard.h create mode 100644 src/string.c create mode 100644 src/string.h diff --git a/makefile b/makefile index af8061e..d1546b7 100644 --- a/makefile +++ b/makefile @@ -17,8 +17,8 @@ build-dir: cp .build/kernel.bin .build/iso/boot/ grub-mkrescue -o .build/nub-os.iso .build/iso/ -.build/kernel.bin: build-dir .build/boot.o .build/kernel.o .build/print.o - $(LD) -Ttext 0x100000 -o .build/kernel.bin .build/boot.o .build/kernel.o .build/print.o +.build/kernel.bin: build-dir .build/boot.o .build/kernel.o .build/print.o .build/idt.o .build/keyboard.o .build/exceptions.o .build/interrupts.o + $(LD) -Ttext 0x100000 -o .build/kernel.bin .build/boot.o .build/kernel.o .build/print.o .build/idt.o .build/keyboard.o .build/exceptions.o .build/interrupts.o .build/kernel.o: build-dir src/kernel.c $(CC) $(CFLAGS) -c -o .build/kernel.o src/kernel.c @@ -26,5 +26,17 @@ build-dir: .build/print.o: build-dir src/print.c $(CC) $(CFLAGS) -c -o .build/print.o src/print.c +.build/idt.o: build-dir src/idt.c + $(CC) $(CFLAGS) -c -o .build/idt.o src/idt.c + +.build/keyboard.o: build-dir src/keyboard.c + $(CC) $(CFLAGS) -c -o .build/keyboard.o src/keyboard.c + +.build/exceptions.o: build-dir src/exceptions.c + $(CC) $(CFLAGS) -c -o .build/exceptions.o src/exceptions.c + +.build/interrupts.o: build-dir src/interrupts.asm + nasm -f elf64 -o .build/interrupts.o src/interrupts.asm + .build/boot.o: build-dir src/boot.asm nasm -f elf64 -o .build/boot.o src/boot.asm \ No newline at end of file diff --git a/src/exceptions.c b/src/exceptions.c new file mode 100644 index 0000000..e21d0fe --- /dev/null +++ b/src/exceptions.c @@ -0,0 +1,30 @@ +#include "print.h" +#include + +void exception_handler(uint64_t* stack) +{ + uint64_t interrupt_num = stack[0]; + uint64_t error_code = stack[1]; + + print("EXCEPTION: "); + if (interrupt_num == 0) + { + print("Division by zero"); + } + else if (interrupt_num == 13) + { + print("General protection fault"); + } + else + { + print("Unknown exception"); + } + print("\nError code: "); + // You'd need to implement number printing here + print("\nSystem halted.\n"); + + while (1) + { + __asm__ volatile("hlt"); + } +} diff --git a/src/idt.c b/src/idt.c new file mode 100644 index 0000000..606123d --- /dev/null +++ b/src/idt.c @@ -0,0 +1,59 @@ +#include "idt.h" +#include "print.h" + +#define IDT_ENTRIES 256 + +struct idt_entry +{ + uint16_t offset_low; + uint16_t selector; + uint8_t ist; + uint8_t type_attr; + uint16_t offset_mid; + uint32_t offset_high; + uint32_t zero; +} __attribute__((packed)); + +struct idt_ptr +{ + uint16_t limit; + uint64_t base; +} __attribute__((packed)); + +static struct idt_entry idt[IDT_ENTRIES]; +static struct idt_ptr idt_pointer; + +extern void isr0(void); +extern void isr13(void); +extern void keyboard_handler_asm(void); + +static void idt_set_gate(uint8_t num, uint64_t handler, uint16_t sel, uint8_t flags) +{ + idt[num].offset_low = handler & 0xFFFF; + idt[num].selector = sel; + idt[num].ist = 0; + idt[num].type_attr = flags; + idt[num].offset_mid = (handler >> 16) & 0xFFFF; + idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF; + idt[num].zero = 0; +} + +void idt_init(void) +{ + idt_pointer.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1; + idt_pointer.base = (uint64_t)&idt; + + for (int i = 0; i < IDT_ENTRIES; i++) + { + idt_set_gate(i, 0, 0, 0); + } + + idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E); + idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E); + idt_set_gate(33, (uint64_t)keyboard_handler_asm, 0x08, 0x8E); + + __asm__ volatile("lidt %0" : : "m"(idt_pointer)); + + print_clr("[success]", FG_GREEN, BG_BLACK); + print(" idt initialized\n"); +} \ No newline at end of file diff --git a/src/idt.h b/src/idt.h new file mode 100644 index 0000000..6576cf9 --- /dev/null +++ b/src/idt.h @@ -0,0 +1,3 @@ +#pragma once + +void idt_init(void); diff --git a/src/interrupts.asm b/src/interrupts.asm new file mode 100644 index 0000000..f3d34b6 --- /dev/null +++ b/src/interrupts.asm @@ -0,0 +1,96 @@ +section .text + +global isr0 +global isr13 +global keyboard_handler_asm + +extern exception_handler +extern keyboard_handler + +isr0: + push 0 + push 0 + jmp exception_common + +isr13: + push 13 + jmp exception_common + +exception_common: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + mov rdi, rsp + call exception_handler + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + + add rsp, 16 + iretq + +keyboard_handler_asm: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + call keyboard_handler + + mov al, 0x20 + out 0x20, al + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + + iretq \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index 694ca13..e2ebec5 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,6 +1,12 @@ +#include "idt.h" +#include "keyboard.h" #include "print.h" void kernel_main(void) { - print("Starting nub-os\n"); -} + idt_init(); + keyboard_init(); + + print("Welcome to nub OS\n"); + print("> "); +} \ No newline at end of file diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100644 index 0000000..7f331e9 --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,80 @@ +#include "print.h" +#include +#include + +#define KEYBOARD_DATA_PORT 0x60 +#define KEYBOARD_STATUS_PORT 0x64 + +static char scancode_to_ascii[] = { 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', + 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ' }; + +static char input_buffer[256]; +static int buffer_index = 0; +static bool key_available = false; + +static uint8_t inb(uint16_t port) +{ + uint8_t result; + __asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} + +void keyboard_handler(void) +{ + uint8_t scancode = inb(KEYBOARD_DATA_PORT); + + if (scancode & 0x80) + { + return; + } + + if (scancode < sizeof(scancode_to_ascii)) + { + char ascii = scancode_to_ascii[scancode]; + if (ascii) + { + if (ascii == '\b') + { + if (buffer_index > 0) + { + buffer_index--; + print("\b \b"); + } + } + else if (ascii == '\n') + { + input_buffer[buffer_index] = '\0'; + print("\n"); + key_available = true; + } + else if (buffer_index < 255) + { + input_buffer[buffer_index++] = ascii; + char str[2] = { ascii, '\0' }; + print(str); + } + } + } +} + +char* keyboard_get_line(void) +{ + buffer_index = 0; + key_available = false; + + while (!key_available) + { + __asm__ volatile("hlt"); + } + + return input_buffer; +} + +void keyboard_init(void) +{ + __asm__ volatile("sti"); + print_clr("[success]", FG_GREEN, BG_BLACK); + print(" keyboard initialized\n"); +} \ No newline at end of file diff --git a/src/keyboard.h b/src/keyboard.h new file mode 100644 index 0000000..b308b43 --- /dev/null +++ b/src/keyboard.h @@ -0,0 +1,4 @@ +#pragma once + +void keyboard_init(void); +char* keyboard_get_line(void); \ No newline at end of file diff --git a/src/print.c b/src/print.c index 3afb162..61e6cd4 100644 --- a/src/print.c +++ b/src/print.c @@ -8,38 +8,6 @@ #define BUF_START 0xb8000 #define BUF_END (BUF_START + BUF_SIZE) -enum FG_COLOR -{ - FG_BLACK = 0x0, - FG_BLUE = 0x1, - FG_GREEN = 0x2, - FG_CYAN = 0x3, - FG_RED = 0x4, - FG_MAGENTA = 0x5, - FG_BROWN = 0x6, - FG_LIGHT_GRAY = 0x7, - FG_DARK_GRAY = 0x8, - FG_LIGHT_BLUE = 0x9, - FG_LIGHT_GREEN = 0xA, - FG_LIGHT_CYAN = 0xB, - FG_LIGHT_RED = 0xC, - FG_LIGHT_MAGENTA = 0xD, - FG_YELLOW = 0xE, - FG_WHITE = 0xF, -}; - -enum BG_COLOR -{ - BG_BLACK = 0x0, - BG_BLUE = 0x1, - BG_GREEN = 0x2, - BG_CYAN = 0x3, - BG_RED = 0x4, - BG_MAGENTA = 0x5, - BG_BROWN = 0x6, - BG_LIGHT_GRAY = 0x7, -}; - typedef struct { uint8_t character; @@ -66,7 +34,7 @@ void scroll(void) } } -void put_char(char c, uint8_t color) +void put_char(char c, FG_COLOR fg_color, BG_COLOR bg_color) { if (c == '\n') { @@ -75,6 +43,7 @@ void put_char(char c, uint8_t color) } else { + uint8_t color = fg_color | bg_color << 4; vga_buffer[cursor_row * COLUMNS + cursor_col] = (vga_char){ c, color }; cursor_col++; } @@ -94,11 +63,14 @@ void put_char(char c, uint8_t color) void print(const char* string) { - uint8_t color = FG_WHITE | BG_BLACK << 4; + print_clr(string, FG_WHITE, BG_BLACK); +} +void print_clr(const char* string, FG_COLOR fg_color, BG_COLOR bg_color) +{ for (int i = 0; string[i]; i++) { - put_char(string[i], color); + put_char(string[i], fg_color, bg_color); } } diff --git a/src/print.h b/src/print.h index e9bac66..e3d0df9 100644 --- a/src/print.h +++ b/src/print.h @@ -1,8 +1,40 @@ +#pragma once #include -void kernel_print(const char* string); +typedef enum +{ + FG_BLACK = 0x0, + FG_BLUE = 0x1, + FG_GREEN = 0x2, + FG_CYAN = 0x3, + FG_RED = 0x4, + FG_MAGENTA = 0x5, + FG_BROWN = 0x6, + FG_LIGHT_GRAY = 0x7, + FG_DARK_GRAY = 0x8, + FG_LIGHT_BLUE = 0x9, + FG_LIGHT_GREEN = 0xA, + FG_LIGHT_CYAN = 0xB, + FG_LIGHT_RED = 0xC, + FG_LIGHT_MAGENTA = 0xD, + FG_YELLOW = 0xE, + FG_WHITE = 0xF, +} FG_COLOR; -void put_char(char c, uint8_t color); +typedef enum +{ + BG_BLACK = 0x0, + BG_BLUE = 0x1, + BG_GREEN = 0x2, + BG_CYAN = 0x3, + BG_RED = 0x4, + BG_MAGENTA = 0x5, + BG_BROWN = 0x6, + BG_LIGHT_GRAY = 0x7, +} BG_COLOR; + +void put_char(char c, FG_COLOR fg_color, BG_COLOR bg_color); void print(const char* string); +void print_clr(const char* string, FG_COLOR fg_color, BG_COLOR bg_color); void clear_screen(void); void set_cursor_position(int row, int col); \ No newline at end of file diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..0366ec7 --- /dev/null +++ b/src/string.c @@ -0,0 +1,10 @@ +int strcmp(const char* a, const char* b) +{ + while ((*a != '\0' && *b != '\0') && *a == *b) + { + a++; + b++; + } + + return (*a == *b) ? 0 : (*a > *b) ? 1 : -1; +} diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000..f326318 --- /dev/null +++ b/src/string.h @@ -0,0 +1,3 @@ +#pragma once + +int strcmp(const char* a, const char* b); \ No newline at end of file