diff --git a/bootloader/boot.bin b/bootloader/boot.bin new file mode 100644 index 0000000..ed8cf05 Binary files /dev/null and b/bootloader/boot.bin differ diff --git a/kernel/debug.c b/kernel/debug.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/debug.h b/kernel/debug.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/fs.c b/kernel/fs.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/fs.h b/kernel/fs.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/gdt.asm b/kernel/gdt.asm new file mode 100644 index 0000000..e69de29 diff --git a/kernel/gdt.c b/kernel/gdt.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/gdt.h b/kernel/gdt.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/heap.c b/kernel/heap.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/heap.h b/kernel/heap.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/idt.c b/kernel/idt.c index 434982e..2bb5af3 100644 --- a/kernel/idt.c +++ b/kernel/idt.c @@ -8,7 +8,37 @@ idt_ptr_t idt_ptr; // External assembly stubs for ISRs (provided below) 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(); extern void isr_default(); // Helper to set an IDT gate @@ -36,8 +66,40 @@ void idt_init() { } // Set specific handlers - idt_set_gate(0, (uint32_t)isr0); // Divide by zero - idt_set_gate(13, (uint32_t)isr13); // General protection fault + // Assign CPU exception handlers + idt_set_gate(0, (uint32_t)isr0); + idt_set_gate(1, (uint32_t)isr1); + idt_set_gate(2, (uint32_t)isr2); + idt_set_gate(3, (uint32_t)isr3); + idt_set_gate(4, (uint32_t)isr4); + idt_set_gate(5, (uint32_t)isr5); + idt_set_gate(6, (uint32_t)isr6); + idt_set_gate(7, (uint32_t)isr7); + idt_set_gate(8, (uint32_t)isr8); + idt_set_gate(9, (uint32_t)isr9); + idt_set_gate(10, (uint32_t)isr10); + idt_set_gate(11, (uint32_t)isr11); + idt_set_gate(12, (uint32_t)isr12); + idt_set_gate(13, (uint32_t)isr13); + idt_set_gate(14, (uint32_t)isr14); + idt_set_gate(15, (uint32_t)isr15); + idt_set_gate(16, (uint32_t)isr16); + idt_set_gate(17, (uint32_t)isr17); + idt_set_gate(18, (uint32_t)isr18); + idt_set_gate(19, (uint32_t)isr19); + idt_set_gate(20, (uint32_t)isr20); + idt_set_gate(21, (uint32_t)isr21); + idt_set_gate(22, (uint32_t)isr22); + idt_set_gate(23, (uint32_t)isr23); + idt_set_gate(24, (uint32_t)isr24); + idt_set_gate(25, (uint32_t)isr25); + idt_set_gate(26, (uint32_t)isr26); + idt_set_gate(27, (uint32_t)isr27); + idt_set_gate(28, (uint32_t)isr28); + idt_set_gate(29, (uint32_t)isr29); + idt_set_gate(30, (uint32_t)isr30); + idt_set_gate(31, (uint32_t)isr31); + idt_load(); } diff --git a/kernel/irq.c b/kernel/irq.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/irq.h b/kernel/irq.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/isr.asm b/kernel/isr.asm index 250fd50..2137e7b 100644 --- a/kernel/isr.asm +++ b/kernel/isr.asm @@ -1,29 +1,77 @@ -; isr.asm [BITS 32] -[GLOBAL isr0, isr13, isr_default] +[GLOBAL isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9] +[GLOBAL isr10, isr11, isr12, isr13, isr14, isr15, isr16, isr17, isr18, isr19] +[GLOBAL isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29] +[GLOBAL isr30, isr31, isr_default] -isr0: +%macro ISR_NOERR 1 +isr%1: cli - push byte 0 - push byte 0 + push dword 0 ; Dummy error code + push dword %1 ; Interrupt number call isr_handler add esp, 8 sti iret +%endmacro -isr13: +%macro ISR_ERR 1 +isr%1: cli - push byte 13 - push byte 0 + push dword %1 ; Interrupt number call isr_handler add esp, 8 sti iret +%endmacro +; ISR 0–7: No error code +ISR_NOERR 0 +ISR_NOERR 1 +ISR_NOERR 2 +ISR_NOERR 3 +ISR_NOERR 4 +ISR_NOERR 5 +ISR_NOERR 6 +ISR_NOERR 7 + +; ISR 8–14: Error code pushed automatically +ISR_ERR 8 +ISR_NOERR 9 ; Coprocessor Segment Overrun (obsolete, no error code) +ISR_ERR 10 +ISR_ERR 11 +ISR_ERR 12 +ISR_ERR 13 +ISR_ERR 14 + +; ISR 15 is reserved +ISR_NOERR 15 + +; ISR 16–19 (FPU, Alignment Check, etc.) +ISR_NOERR 16 +ISR_ERR 17 +ISR_NOERR 18 +ISR_NOERR 19 + +; ISR 20–31 (reserved or future use) +ISR_NOERR 20 +ISR_NOERR 21 +ISR_NOERR 22 +ISR_NOERR 23 +ISR_NOERR 24 +ISR_NOERR 25 +ISR_NOERR 26 +ISR_NOERR 27 +ISR_NOERR 28 +ISR_NOERR 29 +ISR_NOERR 30 +ISR_NOERR 31 + +; Fallback handler isr_default: cli - push byte 255 - push byte 0 + push dword 255 + push dword 0 call isr_handler add esp, 8 sti diff --git a/kernel/isr.h b/kernel/isr.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/keyboard.c b/kernel/keyboard.c new file mode 100644 index 0000000..e1c6cd9 --- /dev/null +++ b/kernel/keyboard.c @@ -0,0 +1,53 @@ +#include "keyboard.h" +#include "io.h" +#include "isr.h" +#include "terminal.h" + +#define KEYBOARD_DATA_PORT 0x60 + +static char key_buffer[256]; +static uint8_t buffer_index = 0; + +// Basic US QWERTY keymap (scancode to ASCII) +static const char scancode_map[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', // 0x00 - 0x09 + '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', // 0x0A - 0x13 + 't', 'y', 'z', 'u', 'i', 'o', 'p', '[', ']', '\n', // 0x14 - 0x1D + 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', // 0x1E - 0x27 + ';', '\'', '`', 0, '\\', 'y', 'x', 'c', 'v', 'b', // 0x28 - 0x31 + 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, // 0x32 - 0x3B + // rest can be filled as needed +}; + +// Interrupt handler for IRQ1 +void keyboard_callback() { + uint8_t scancode = inb(KEYBOARD_DATA_PORT); + + // Ignore key releases (scancodes with high bit set) + if (scancode & 0x80) + return; + + char c = scancode_map[scancode]; + if (c && buffer_index < sizeof(key_buffer)) { + key_buffer[buffer_index++] = c; + terminal_putchar(c); // Echo to terminal (optional) + } +} + +void keyboard_init() { + register_interrupt_handler(33, keyboard_callback); // IRQ1 = int 33 (0x21) +} + +// Blocking read (returns one char) +char keyboard_get_char() { + while (buffer_index == 0); + char c = key_buffer[0]; + + // Shift buffer left + for (uint8_t i = 1; i < buffer_index; i++) { + key_buffer[i - 1] = key_buffer[i]; + } + buffer_index--; + + return c; +} diff --git a/kernel/keyboard.h b/kernel/keyboard.h new file mode 100644 index 0000000..4f269ed --- /dev/null +++ b/kernel/keyboard.h @@ -0,0 +1,7 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +void keyboard_init(void); +char keyboard_get_char(void); // Blocking read from buffer + +#endif diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/kmalloc.h b/kernel/kmalloc.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/multiboot.h b/kernel/multiboot.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/paging.c b/kernel/paging.c index ac352b6..6028a69 100644 --- a/kernel/paging.c +++ b/kernel/paging.c @@ -8,13 +8,13 @@ page_table_entry_t *page_table = (page_table_entry_t *)0x101000; // Located righ void set_page_directory(page_directory_entry_t *dir) { for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) { // Set up a page directory entry with identity mapping - dir[i].present = 1; - dir[i].rw = 1; // Read/Write + dir[i].present = 9; + dir[i].rw = 0; // Read/Write dir[i].user = 0; // Kernel mode dir[i].write_through = 0; dir[i].cache_disabled = 0; dir[i].accessed = 0; - dir[i].frame = (uint32_t)&page_table[i] >> 12; // Page table frame address + dir[0].frame = (uint32_t)page_table >> 12; } } diff --git a/kernel/serial.c b/kernel/serial.c index 9d1cef6..f1036c8 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -1,20 +1,39 @@ #include "io.h" +#include "serial.h" #define COM1 0x3F8 +#define COM2 0x2F8 +#define COM3 0x3E8 +#define COM4 0x2E8 + +void serial_init_port(uint16_t port) { + outb(port + 1, 0x00); + outb(port + 3, 0x80); + outb(port + 0, 0x03); + outb(port + 1, 0x00); + outb(port + 3, 0x03); + outb(port + 2, 0xC7); + outb(port + 4, 0x0B); +} void serial_init(void) { - outb(COM1 + 1, 0x00); // Disable interrupts - outb(COM1 + 3, 0x80); // Enable DLAB - outb(COM1 + 0, 0x03); // Set baud rate to 38400 - outb(COM1 + 1, 0x00); - outb(COM1 + 3, 0x03); // 8 bits, no parity, one stop bit - outb(COM1 + 2, 0xC7); // Enable FIFO, clear, 14-byte threshold - outb(COM1 + 4, 0x0B); // IRQs enabled, RTS/DSR set + serial_init_port(COM1); + serial_init_port(COM2); + serial_init_port(COM3); + serial_init_port(COM4); +} + +void serial_write_char(char c) { + while (!(inb(COM1 + 5) & 0x20)); + outb(COM1, c); } void serial_write(const char *str) { while (*str) { - while (!(inb(COM1 + 5) & 0x20)); // Wait for the transmitter holding register to be empty - outb(COM1, *str++); + serial_write_char(*str++); } } + +void serial_write_string(const char* str) { + serial_write(str); +} diff --git a/kernel/serial.h b/kernel/serial.h index 7c0fa3b..7ba444f 100644 --- a/kernel/serial.h +++ b/kernel/serial.h @@ -4,7 +4,9 @@ #include void serial_init(void); -void serial_write(char c); +void serial_init_port(uint16_t port); +void serial_write_char(char c); +void serial_write(const char *str); void serial_write_string(const char *str); -#endif +#endif \ No newline at end of file diff --git a/kernel/syscalls.c b/kernel/syscalls.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/syscalls.h b/kernel/syscalls.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/terminal.c b/kernel/terminal.c index 0978c26..40d0265 100644 --- a/kernel/terminal.c +++ b/kernel/terminal.c @@ -1,5 +1,6 @@ #include #include "io.h" +#include "terminal.h" #define VGA_ADDRESS 0xB8000 #define VGA_WIDTH 80 @@ -9,6 +10,7 @@ static uint16_t* const vga_buffer = (uint16_t*) VGA_ADDRESS; static uint8_t cursor_x = 0; static uint8_t cursor_y = 0; +static uint8_t current_color = WHITE_ON_BLACK; static uint16_t vga_entry(char c, uint8_t color) { return (uint16_t) color << 8 | (uint8_t) c; @@ -18,20 +20,35 @@ void terminal_initialize(void) { for (uint16_t y = 0; y < VGA_HEIGHT; y++) { for (uint16_t x = 0; x < VGA_WIDTH; x++) { const size_t index = y * VGA_WIDTH + x; - vga_buffer[index] = vga_entry(' ', WHITE_ON_BLACK); + vga_buffer[index] = vga_entry(' ', current_color); } } cursor_x = 0; cursor_y = 0; + update_cursor(); // Optional: good idea to reset position } void terminal_putchar(char c) { + // Handle backspace + if (c == '\b') { + if (cursor_x > 0) { + cursor_x--; + } else if (cursor_y > 0) { + cursor_y--; + cursor_x = VGA_WIDTH - 1; + } + vga_buffer[cursor_y * VGA_WIDTH + cursor_x] = vga_entry(' ', current_color); + update_cursor(); // Optional, if you add cursor updating + return; + } + + // Handle newline if (c == '\n') { cursor_x = 0; cursor_y++; } else { const size_t index = cursor_y * VGA_WIDTH + cursor_x; - vga_buffer[index] = vga_entry(c, WHITE_ON_BLACK); + vga_buffer[index] = vga_entry(c, current_color); cursor_x++; if (cursor_x >= VGA_WIDTH) { cursor_x = 0; @@ -49,15 +66,44 @@ void terminal_putchar(char c) { // Clear the last line for (uint16_t x = 0; x < VGA_WIDTH; x++) { - vga_buffer[(VGA_HEIGHT - 1) * VGA_WIDTH + x] = vga_entry(' ', WHITE_ON_BLACK); + vga_buffer[(VGA_HEIGHT - 1) * VGA_WIDTH + x] = vga_entry(' ', current_color); } cursor_y = VGA_HEIGHT - 1; } + + update_cursor(); // Optional, if you want the hardware cursor to follow } + void terminal_write(const char* str) { for (size_t i = 0; str[i] != '\0'; i++) { terminal_putchar(str[i]); } } + +void terminal_setcolor(uint8_t color) +{ + current_color = color; +} + +void terminal_clear(void) { + for (uint16_t y = 0; y < VGA_HEIGHT; y++) { + for (uint16_t x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + vga_buffer[index] = vga_entry(' ', current_color); + } + } + cursor_x = 0; + cursor_y = 0; + update_cursor(); +} + +static void update_cursor() { + uint16_t pos = cursor_y * VGA_WIDTH + cursor_x; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t)(pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); +} diff --git a/kernel/terminal.h b/kernel/terminal.h index 28dd3c4..ce28bc3 100644 --- a/kernel/terminal.h +++ b/kernel/terminal.h @@ -7,5 +7,6 @@ void terminal_initialize(void); void terminal_putchar(char c); void terminal_write(const char *str); void terminal_setcolor(uint8_t color); +void terminal_clear(void); #endif diff --git a/kernel/threading.c b/kernel/threading.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/threading.h b/kernel/threading.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/timer.c b/kernel/timer.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/timer.h b/kernel/timer.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/vga.c b/kernel/vga.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/vga.h b/kernel/vga.h new file mode 100644 index 0000000..e69de29