diff --git a/makefile b/makefile index bc44d83..6b9aafc 100644 --- a/makefile +++ b/makefile @@ -6,8 +6,8 @@ CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23 -g LDFLAGS = -g ASFLAGS = -f elf64 -g -F dwarf -SRC_C := src/kernel.c src/string.c src/vga.c -SRC_ASM := src/boot.asm +SRC_C := src/kernel.c src/string.c src/vga.c src/idt.c src/keyboard.c +SRC_ASM := src/boot.asm src/idt_stub.asm OBJ_C := $(SRC_C:src/%.c=.build/%.o) OBJ_ASM := $(SRC_ASM:src/%.asm=.build/%.o) diff --git a/src/idt.c b/src/idt.c index defb99e..38d8d83 100644 --- a/src/idt.c +++ b/src/idt.c @@ -1,8 +1,5 @@ #include "idt.h" #include "vga.h" -#include -#include -#include #define IDT_SIZE 256 @@ -13,19 +10,19 @@ typedef struct { - uint16_t address_low; - uint16_t selector; - uint8_t ist; - uint8_t flags; - uint16_t address_mid; - uint32_t address_high; - uint32_t reserved; + u16 address_low; + u16 selector; + u8 ist; + u8 flags; + u16 address_mid; + u32 address_high; + u32 reserved; } __attribute__((packed)) interrupt_descriptor; typedef struct { - uint16_t limit; - uint64_t base; + u16 limit; + u64 base; } __attribute__((packed)) idtr_t; extern void* isr_stub_table[]; @@ -70,7 +67,7 @@ static interrupt_descriptor idt[IDT_SIZE]; static void pic_remap(int offset1, int offset2) { - uint8_t a1, a2; + u8 a1, a2; a1 = inb(PIC1_DATA); a2 = inb(PIC2_DATA); @@ -91,7 +88,7 @@ static void pic_remap(int offset1, int offset2) outb(PIC2_DATA, a2); } -static void pic_send_eoi(uint8_t irq) +static void pic_send_eoi(u8 irq) { if (irq >= 8) { @@ -101,18 +98,18 @@ static void pic_send_eoi(uint8_t irq) outb(PIC1_COMMAND, 0x20); } -void register_irq_handler(uint8_t irq, irq_handler_t handler) +void register_irq_handler(u8 irq, irq_handler_t handler) { irq_handlers[irq] = handler; } -static inline void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl) +static inline void idt_set_descriptor(u8 vector, void* handler, u8 dpl) { interrupt_descriptor* entry = &idt[vector]; - entry->address_low = (uint64_t)handler & 0xFFFF; - entry->address_mid = ((uint64_t)handler >> 16) & 0xFFFF; - entry->address_high = (uint64_t)handler >> 32; + entry->address_low = (u64)handler & 0xFFFF; + entry->address_mid = ((u64)handler >> 16) & 0xFFFF; + entry->address_high = (u64)handler >> 32; entry->selector = 0x08; entry->flags = 0b1110 | ((dpl & 0b11) << 5) | (1 << 7); entry->ist = 0; @@ -130,7 +127,7 @@ void init_idt(void) idtr_t idtr = { .base = (uintptr_t)&idt[0], - .limit = (uint16_t)sizeof(interrupt_descriptor) * IDT_SIZE - 1, + .limit = (u16)sizeof(interrupt_descriptor) * IDT_SIZE - 1, }; __asm__ volatile("lidt %0" : : "m"(idtr)); @@ -155,7 +152,7 @@ void handle_isr(isr_frame_t* frame) } else if (frame->int_no < 48) { - uint8_t irq = frame->int_no - 32; + u8 irq = frame->int_no - 32; if (irq_handlers[irq]) { diff --git a/src/idt.h b/src/idt.h index 9b9f0e4..c5e84f1 100644 --- a/src/idt.h +++ b/src/idt.h @@ -1,30 +1,30 @@ #pragma once -#include +#include "typedef.h" typedef struct { - uint64_t r15, r14, r13, r12, r11, r10, r9, r8; - uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; - uint64_t int_no; - uint64_t err_code; - uint64_t rip, cs, rflags, rsp, ss; + u64 r15, r14, r13, r12, r11, r10, r9, r8; + u64 rbp, rdi, rsi, rdx, rcx, rbx, rax; + u64 int_no; + u64 err_code; + u64 rip, cs, rflags, rsp, ss; } __attribute__((packed)) isr_frame_t; typedef void (*irq_handler_t)(const isr_frame_t*); void init_idt(void); -static inline void outb(uint16_t port, uint8_t val) +static inline void outb(u16 port, u8 val) { __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); } -static inline uint8_t inb(uint16_t port) +static inline u8 inb(u16 port) { - uint8_t ret; + u8 ret; __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); return ret; } -void register_irq_handler(uint8_t irq, irq_handler_t handler); \ No newline at end of file +void register_irq_handler(u8 irq, irq_handler_t handler); \ No newline at end of file diff --git a/src/idt_stub.asm b/src/idt_stub.asm new file mode 100644 index 0000000..bed39b3 --- /dev/null +++ b/src/idt_stub.asm @@ -0,0 +1,109 @@ +extern handle_isr + +isr_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 handle_isr + + 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 + +%macro ISR_NOERR 1 +isr_stub_%1: + push qword 0 + push qword %1 + jmp isr_common +%endmacro + +%macro ISR_ERR 1 +isr_stub_%1: + push qword %1 + jmp isr_common +%endmacro + +; CPU exceptions 0-31 +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_ERR 8 +ISR_NOERR 9 +ISR_ERR 10 +ISR_ERR 11 +ISR_ERR 12 +ISR_ERR 13 +ISR_ERR 14 +ISR_NOERR 15 +ISR_NOERR 16 +ISR_ERR 17 +ISR_NOERR 18 +ISR_NOERR 19 +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_ERR 30 +ISR_NOERR 31 + +%macro GENERATE_ISRS 2 + %assign i %1 + %rep (%2 - %1 + 1) + ISR_NOERR i + %assign i i+1 + %endrep +%endmacro + +GENERATE_ISRS 32, 255 + +%macro GENERATE_ISR_TABLE 2 + %assign i %1 + %rep (%2 - %1 + 1) + dq isr_stub_%[i] + %assign i i+1 + %endrep +%endmacro + +global isr_stub_table +isr_stub_table: +GENERATE_ISR_TABLE 0, 255 \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index 2d4054d..1127b88 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,15 +1,22 @@ #include "kernel.h" -#include "multiboot.h" +#include "idt.h" +#include "keyboard.h" #include "vga.h" -#include -#include -void kernel_main(multiboot_info_t* multiboot_info) +void kernel_main() { vga_clear(); vga_print_success(); vga_print(" VGA intialzied\n"); + init_idt(); + vga_print_success(); + vga_print(" IDT intialzied\n"); + + init_keyboard(); + vga_print_success(); + vga_print(" Keyboard intialzied\n"); + vga_print("\nWelcome to nub OS\n"); while (true) diff --git a/src/kernel.h b/src/kernel.h index 3cafb48..bb46304 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -1,3 +1,3 @@ #pragma once -void kernel_panic(); +void kernel_panic(); \ No newline at end of file diff --git a/src/keyboard.c b/src/keyboard.c index 10bd254..cb3bb1e 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2,8 +2,6 @@ #include "idt.h" #include "kernel.h" #include "vga.h" -#include -#include #define SCANCODE_LEFT_SHIFT 42 #define SCANCODE_RIGHT_SHIFT 54 @@ -34,7 +32,7 @@ bool caps_lock = false; static keyboard_handler_t keyboard_handlers[KEYBOARD_HANDLERS_LENGTH]; static int handler_index = 0; -char scan_code_to_ascii(uint8_t scan_code) +char scan_code_to_ascii(u8 scan_code) { if (scan_code >= 128) { @@ -53,8 +51,8 @@ char scan_code_to_ascii(uint8_t scan_code) void handle_keyboard(const isr_frame_t* frame) { - uint8_t code = inb(0x60); - uint8_t scan_code = code & 0x7F; + u8 code = inb(0x60); + u8 scan_code = code & 0x7F; bool pressed = (code & 0x80) == 0; switch (scan_code) diff --git a/src/keyboard.h b/src/keyboard.h index 104a409..4573070 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -1,11 +1,10 @@ #pragma once -#include -#include +#include "typedef.h" typedef struct { - uint8_t scan_code; + u8 scan_code; bool pressed; bool shift; bool caps_lock; @@ -16,4 +15,4 @@ typedef void (*keyboard_handler_t)(const keyboard_event_t*); void init_keyboard(); void register_keypress_handler(keyboard_handler_t handler); -char scan_code_to_ascii(uint8_t scan_code); \ No newline at end of file +char scan_code_to_ascii(u8 scan_code); \ No newline at end of file diff --git a/src/multiboot.h b/src/multiboot.h index 1036405..73ffb30 100644 --- a/src/multiboot.h +++ b/src/multiboot.h @@ -1,58 +1,59 @@ #pragma once -#include + +#include "typedef.h" typedef struct multiboot_info { - uint32_t flags; // required + u32 flags; // required // Available if flags[0] is set - uint32_t mem_lower; - uint32_t mem_upper; + u32 mem_lower; + u32 mem_upper; // Available if flags[1] is set - uint32_t boot_device; + u32 boot_device; // Available if flags[2] is set - uint32_t cmdline; + u32 cmdline; // Available if flags[3] is set - uint32_t mods_count; - uint32_t mods_addr; + u32 mods_count; + u32 mods_addr; // Available if flags[4] or flags[5] is set - uint8_t syms[16]; // 28 - 40 bytes, exact layout may differ depending on a.out or ELF + u8 syms[16]; // 28 - 40 bytes, exact layout may differ depending on a.out or ELF // Available if flags[6] is set - uint32_t mmap_length; - uint32_t mmap_addr; + u32 mmap_length; + u32 mmap_addr; // Available if flags[7] is set - uint32_t drives_length; - uint32_t drives_addr; + u32 drives_length; + u32 drives_addr; // Available if flags[8] is set - uint32_t config_table; + u32 config_table; // Available if flags[9] is set - uint32_t boot_loader_name; + u32 boot_loader_name; // Available if flags[10] is set - uint32_t apm_table; + u32 apm_table; // Available if flags[11] is set - uint32_t vbe_control_info; - uint32_t vbe_mode_info; - uint16_t vbe_mode; - uint16_t vbe_interface_seg; - uint16_t vbe_interface_off; - uint16_t vbe_interface_len; + u32 vbe_control_info; + u32 vbe_mode_info; + u16 vbe_mode; + u16 vbe_interface_seg; + u16 vbe_interface_off; + u16 vbe_interface_len; // Available if flags[12] is set - uint64_t framebuffer_addr; // 64-bit for large memory addresses - uint32_t framebuffer_pitch; - uint32_t framebuffer_width; - uint32_t framebuffer_height; - uint8_t framebuffer_bpp; - uint8_t framebuffer_type; - uint8_t color_info[6]; // 110-115 bytes + u64 framebuffer_addr; // 64-bit for large memory addresses + u32 framebuffer_pitch; + u32 framebuffer_width; + u32 framebuffer_height; + u8 framebuffer_bpp; + u8 framebuffer_type; + u8 color_info[6]; // 110-115 bytes } __attribute__((packed)) multiboot_info_t; \ No newline at end of file diff --git a/src/string.c b/src/string.c index 2880649..ecf9ea6 100644 --- a/src/string.c +++ b/src/string.c @@ -1,5 +1,4 @@ #include "string.h" -#include int strcmp(const char* a, const char* b) { @@ -26,7 +25,7 @@ void reverse(char* str, size_t length) } } -int uitoa(uint32_t value, char* buffer) +int uitoa(u64 value, char* buffer) { int i = 0; if (value == 0) @@ -47,7 +46,7 @@ int uitoa(uint32_t value, char* buffer) return i; } -int itoa(int32_t value, char* buffer) +int itoa(i64 value, char* buffer) { int i = 0; @@ -59,16 +58,16 @@ int itoa(int32_t value, char* buffer) } bool negative = false; - uint32_t v; + u64 v; if (value < 0) { negative = true; - v = (uint32_t)(-value); + v = (u64)(-value); } else { - v = (uint32_t)value; + v = (u64)value; } while (v > 0) diff --git a/src/string.h b/src/string.h index 5b535e2..853d7fe 100644 --- a/src/string.h +++ b/src/string.h @@ -1,9 +1,8 @@ #pragma once -#include -#include +#include "typedef.h" int strcmp(const char* a, const char* b); void reverse(char* str, size_t length); -int uitoa(uint32_t value, char* buffer); -int itoa(int32_t value, char* buffer); \ No newline at end of file +int uitoa(u64 value, char* buffer); +int itoa(i64 value, char* buffer); \ No newline at end of file diff --git a/src/typedef.h b/src/typedef.h new file mode 100644 index 0000000..85573fb --- /dev/null +++ b/src/typedef.h @@ -0,0 +1,16 @@ +#pragma once + +typedef unsigned char u8; +typedef signed char i8; + +typedef unsigned short u16; +typedef signed short i16; + +typedef unsigned int u32; +typedef signed int i32; + +typedef unsigned long long u64; +typedef signed long long i64; + +typedef u64 size_t; +typedef u64 uintptr_t; diff --git a/src/vga.c b/src/vga.c index 301324c..86976d6 100644 --- a/src/vga.c +++ b/src/vga.c @@ -1,37 +1,34 @@ #include "vga.h" #include "string.h" -#include -#include -#include #define ROWS 25 #define COLUMNS 80 typedef struct { - uint8_t character; - uint8_t color; + u8 character; + u8 color; } vga_char; vga_char* vga_buffer = (vga_char*)0xb8000; -uint8_t cursor_row = 0; -uint8_t cursor_col = 0; +u8 cursor_row = 0; +u8 cursor_col = 0; -void vga_set_char(uint8_t row, uint8_t col, vga_char character) +void vga_set_char(u8 row, u8 col, vga_char character) { vga_buffer[COLUMNS * row + col] = character; } -vga_char vga_char_at(uint8_t row, uint8_t col) +vga_char vga_char_at(u8 row, u8 col) { return vga_buffer[COLUMNS * row + col]; } void vga_clear(void) { - for (uint8_t row = 0; row < ROWS; row++) + for (u8 row = 0; row < ROWS; row++) { - for (uint8_t col = 0; col < COLUMNS; col++) + for (u8 col = 0; col < COLUMNS; col++) { vga_char character = { .character = ' ', @@ -45,7 +42,7 @@ void vga_clear(void) cursor_col = 0; } -void vga_set_cursor_position(uint8_t row, uint8_t col) +void vga_set_cursor_position(u8 row, u8 col) { if (row < ROWS && col < COLUMNS) { @@ -71,7 +68,7 @@ void vga_print_char_colored(char character, vga_color_t color) } case '\t': { - uint8_t remainter = cursor_col % 4; + u8 remainter = cursor_col % 4; cursor_col += remainter == 0 ? 4 : remainter; break; } @@ -95,15 +92,15 @@ void vga_print_char_colored(char character, vga_color_t color) if (cursor_row >= ROWS) { - for (uint8_t row = 1; row < ROWS; row++) + for (u8 row = 1; row < ROWS; row++) { - for (uint8_t col = 0; col < COLUMNS; col++) + for (u8 col = 0; col < COLUMNS; col++) { vga_set_char(row - 1, col, vga_char_at(row, col)); } } - for (uint8_t col = 0; col < COLUMNS; col++) + for (u8 col = 0; col < COLUMNS; col++) { vga_char c = { .character = ' ', @@ -118,7 +115,7 @@ void vga_print_char_colored(char character, vga_color_t color) void vga_print_colored(const char* string, vga_color_t color) { - for (uint8_t i = 0; string[i] != '\0'; i++) + for (u8 i = 0; string[i] != '\0'; i++) { vga_print_char_colored(string[i], color); } @@ -138,14 +135,14 @@ void vga_print_error(void) vga_print(" ]"); } -void vga_print_uint(uint32_t value) +void vga_print_uint(u32 value) { char buffer[11]; uitoa(value, buffer); vga_print(buffer); } -void vga_print_int(int32_t value) +void vga_print_int(i32 value) { char buffer[12]; itoa(value, buffer); diff --git a/src/vga.h b/src/vga.h index 0c8a084..4cb97d3 100644 --- a/src/vga.h +++ b/src/vga.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "typedef.h" #define VGA_BLACK 0 #define VGA_BLUE 1 @@ -19,10 +19,10 @@ #define VGA_YELLOW 14 #define VGA_WHITE 15 -typedef uint8_t vga_color_t; +typedef u8 vga_color_t; void vga_clear(void); -void vga_set_cursor_position(uint8_t row, uint8_t col); +void vga_set_cursor_position(u8 row, u8 col); void vga_print_char_colored(char character, vga_color_t color); void vga_print_colored(const char* string, vga_color_t color); @@ -30,8 +30,8 @@ void vga_print_colored(const char* string, vga_color_t color); void vga_print_success(void); void vga_print_error(void); -void vga_print_uint(uint32_t value); -void vga_print_int(int32_t value); +void vga_print_uint(u32 value); +void vga_print_int(i32 value); static inline vga_color_t vga_color(vga_color_t fg_color, vga_color_t bg_color) {