diff --git a/Kernel/Gdt.c b/Kernel/Gdt.c index 6eee4be..141798f 100644 --- a/Kernel/Gdt.c +++ b/Kernel/Gdt.c @@ -1,5 +1,5 @@ #include "Gdt.h" - +#include "Panic.h" // GDT with user mode segments static struct GdtEntry gdt[5]; static struct GdtPtr gdt_ptr; diff --git a/Kernel/Kernel.c b/Kernel/Kernel.c index ef9df2b..5bee05b 100644 --- a/Kernel/Kernel.c +++ b/Kernel/Kernel.c @@ -10,6 +10,7 @@ #include "Gdt.h" #include "UserMode.h" #include "Io.h" +#include "Panic.h" int CurrentLine = 0; int CurrentColumn = 0; void ClearScreen(){ @@ -21,17 +22,23 @@ void ClearScreen(){ } void PrintKernel(const char *str){ + if (!str) return; + char *vidptr = (char*)0xb8000; int offset = (CurrentLine * 80 + CurrentColumn) * 2; for (int k = 0; str[k] != '\0'; k++) { + if (CurrentLine >= 25) break; // Screen bounds + if (str[k] == '\n') { CurrentLine++; CurrentColumn = 0; offset = (CurrentLine * 80 + CurrentColumn) * 2; } else { - vidptr[offset] = str[k]; - vidptr[offset + 1] = 0x03; + if (offset < 80 * 25 * 2) { + vidptr[offset] = str[k]; + vidptr[offset + 1] = 0x03; + } offset += 2; CurrentColumn++; if (CurrentColumn >= 80) { @@ -101,10 +108,15 @@ void PrintKernelInt(int num) { } void PrintKernelAt(const char *str, int line, int col) { - if (line >= 25) line = 24; + if (!str) return; + if (line < 0 || line >= 25) return; + if (col < 0 || col >= 80) return; + char *vidptr = (char*)0xb8000; int offset = (line * 80 + col) * 2; - for (int k = 0; str[k] != '\0'; k++) { + + for (int k = 0; str[k] != '\0' && k < 80; k++) { + if (offset >= 80 * 25 * 2) break; vidptr[offset] = str[k]; vidptr[offset + 1] = 0x03; offset += 2; @@ -164,7 +176,6 @@ void KernelMain(uint32_t magic, uint32_t info) { PrintKernel("Initializing Processes...\n"); ProcessInit(); PrintKernel("Process system ready\n"); - // Create your processes CreateProcess(task1); CreateProcess(task2); CreateProcess(task3); diff --git a/Kernel/Memory.c b/Kernel/Memory.c index 79f8361..853604e 100644 --- a/Kernel/Memory.c +++ b/Kernel/Memory.c @@ -2,6 +2,7 @@ #include "MemOps.h" #include "Cpu.h" #include "Kernel.h" +#include "Panic.h" static uint8_t page_bitmap[BITMAP_SIZE / 8]; static uint64_t total_pages = 0; static uint64_t used_pages = 0; @@ -40,11 +41,19 @@ void* AllocPage(void) { } void FreePage(void* page) { + if (!page) { + Panic("FreePage: NULL pointer"); + } + uint64_t addr = (uint64_t)page; - if (addr < memory_start) return; + if (addr < memory_start) { + Panic("FreePage: Address below memory start"); + } int page_idx = (addr - memory_start) / PAGE_SIZE; - if (page_idx >= total_pages) return; + if (page_idx >= total_pages) { + Panic("FreePage: Page index out of bounds"); + } int byte_idx = page_idx / 8; int bit_idx = page_idx % 8; diff --git a/Kernel/Panic.c b/Kernel/Panic.c new file mode 100644 index 0000000..85e5ae6 --- /dev/null +++ b/Kernel/Panic.c @@ -0,0 +1,39 @@ +#include "Panic.h" +#include "Kernel.h" +#include "Io.h" + +void __attribute__((noreturn)) Panic(const char* message) { + + asm volatile("cli"); + + ClearScreen(); + CurrentLine = 0; + CurrentColumn = 0; + + PrintKernel("[----KERNEL PANIC----]\n"); + PrintKernel(message); + PrintKernel("\n\nSystem halted.\n"); + + while(1) { + asm volatile("hlt"); + } +} + +void __attribute__((noreturn)) PanicWithCode(const char* message, uint64_t error_code) { + asm volatile("cli"); + + ClearScreen(); + CurrentLine = 0; + CurrentColumn = 0; + + PrintKernel("[----KERNEL PANIC----]\n"); + PrintKernel(message); + PrintKernel("\nError Code: "); + PrintKernelHex(error_code); + PrintKernel(" -- Not handled"); + PrintKernel("\n\nSystem halted.\n"); + + while(1) { + asm volatile("hlt"); + } +} \ No newline at end of file diff --git a/Kernel/Panic.h b/Kernel/Panic.h new file mode 100644 index 0000000..58ac511 --- /dev/null +++ b/Kernel/Panic.h @@ -0,0 +1,18 @@ +#ifndef PANIC_H +#define PANIC_H + +#include "stdint.h" + +// Panic function - never returns +void __attribute__((noreturn)) Panic(const char* message); +void __attribute__((noreturn)) PanicWithCode(const char* message, uint64_t error_code); + +// Assert macro +#define ASSERT(condition) \ + do { \ + if (!(condition)) { \ + Panic("Assertion failed: " #condition " at " __FILE__ ":" __LINE__); \ + } \ + } while(0) + +#endif \ No newline at end of file diff --git a/Kernel/Process.c b/Kernel/Process.c index ee1df9d..ea3ab0b 100644 --- a/Kernel/Process.c +++ b/Kernel/Process.c @@ -1,6 +1,7 @@ #include "Process.h" #include "Kernel.h" #include "Memory.h" +#include "Panic.h" #include "Io.h" static Process processes[MAX_PROCESSES]; static uint32_t next_pid = 1; @@ -40,7 +41,14 @@ void ProcessInit(void) { } uint32_t CreateProcess(void (*entry_point)(void)) { - if (process_count >= MAX_PROCESSES) return 0; + if (!entry_point) { + Panic("CreateProcess: NULL entry point"); + } + + if (process_count >= MAX_PROCESSES) { + Panic("CreateProcess: Too many processes"); + } + // Find free slot int slot = -1; for (int i = 1; i < MAX_PROCESSES; i++) { @@ -49,11 +57,15 @@ uint32_t CreateProcess(void (*entry_point)(void)) { break; } } - if (slot == -1) return 0; + if (slot == -1) { + Panic("CreateProcess: No free process slots"); + } // Allocate stack void* stack = AllocPage(); - if (!stack) return 0; + if (!stack) { + Panic("CreateProcess: Failed to allocate stack"); + } // Initialize a process processes[slot].pid = next_pid++; @@ -126,6 +138,14 @@ void Schedule(void) { void ScheduleFromInterrupt(struct Registers* regs) { + if (!regs) { + Panic("ScheduleFromInterrupt: NULL registers"); + } + + if (current_process >= MAX_PROCESSES) { + Panic("ScheduleFromInterrupt: Invalid current process"); + } + if (process_count <= 1) return; // Find next ready process @@ -200,6 +220,9 @@ void ScheduleFromInterrupt(struct Registers* regs) { } Process* GetCurrentProcess(void) { + if (current_process >= MAX_PROCESSES) { + Panic("GetCurrentProcess: Invalid current process index"); + } return &processes[current_process]; } diff --git a/Kernel/Syscall.c b/Kernel/Syscall.c index 5a5756e..cec323e 100644 --- a/Kernel/Syscall.c +++ b/Kernel/Syscall.c @@ -2,9 +2,13 @@ #include "Kernel.h" #include "Process.h" #include "Idt.h" +#include "Panic.h" extern void SyscallEntry(void); uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3) { Process* current = GetCurrentProcess(); + if (!current) { + Panic("Syscall from invalid process"); + } switch (syscall_num) { case SYS_EXIT: // Terminate current process @@ -17,6 +21,13 @@ uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint case SYS_WRITE: // arg1 = fd (ignored for now), arg2 = buffer, arg3 = count if (arg1 == 1) { // stdout + if (!arg2) { + return -1; // NULL buffer + } + if (arg3 > 4096) { + return -1; // Buffer too large + } + char* buffer = (char*)arg2; for (uint64_t i = 0; i < arg3; i++) { if (buffer[i] == '\0') break; @@ -24,6 +35,7 @@ uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint if (CurrentColumn >= 80) { CurrentLine++; CurrentColumn = 0; + if (CurrentLine >= 25) CurrentLine = 24; // Screen bounds } } return arg3; diff --git a/Kernel/UserMode.c b/Kernel/UserMode.c index ed75faf..350b994 100644 --- a/Kernel/UserMode.c +++ b/Kernel/UserMode.c @@ -2,11 +2,14 @@ #include "Memory.h" #include "Process.h" #include "Gdt.h" +#include "Panic.h" void JumpToUserMode(void (*user_function)(void)) { // Allocate user stack void* user_stack = AllocPage(); - if (!user_stack) return; + if (!user_stack) { + Panic("Failed to allocate user stack"); + } uint64_t user_stack_top = (uint64_t)user_stack + STACK_SIZE; diff --git a/meson.build b/meson.build index 264a3f9..cf98d06 100644 --- a/meson.build +++ b/meson.build @@ -51,7 +51,8 @@ c_sources = [ 'Kernel/Process.c', 'Kernel/Syscall.c', 'Kernel/Gdt.c', - 'Kernel/UserMode.c' + 'Kernel/UserMode.c', + 'Kernel/Panic.c' ] # Compile assembly files