From 602b4c3aab990709464909942c88a85339376b2f Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:07:39 +0300 Subject: [PATCH 1/8] Add security checker implementation Implement security checker with task integrity, stack overflow, heap integrity, syscall bounds, memory safety, driver state, and kernel structure checks. --- .../KernelServices/SecurityChecker/securchk.c | 468 ++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 Kernel/KernelServices/SecurityChecker/securchk.c diff --git a/Kernel/KernelServices/SecurityChecker/securchk.c b/Kernel/KernelServices/SecurityChecker/securchk.c new file mode 100644 index 0000000..c761d91 --- /dev/null +++ b/Kernel/KernelServices/SecurityChecker/securchk.c @@ -0,0 +1,468 @@ +#include "securchk.h" + +#include +#include +#include +#include +#include +#include + +extern task_t* task_list; +extern task_t* current; + +static int g_initialized = 0; + +/* ============================================================ + String / Number Helpers (freestanding - no libc) + ============================================================ */ + +static void sc_itoa(uint32_t num, char* buf, int sz) { + if (!buf || sz <= 0) return; + int i = 0; + if (num == 0) { buf[i++] = '0'; } + else { + char tmp[12]; int t = 0; + while (num > 0) { tmp[t++] = (num % 10) + '0'; num /= 10; } + while (t > 0 && i < sz - 1) buf[i++] = tmp[--t]; + } + buf[i] = '\0'; +} + +static void sc_prt(const char* s) { + if (s) vga_print_scr_nw(s); +} + +static void sc_prt_dec(uint32_t n) { + char b[12]; sc_itoa(n, b, sizeof(b)); sc_prt(b); +} + +static void sc_prt_hex(uint32_t n) { + const char* hx = "0123456789ABCDEF"; + sc_prt("0x"); + for (int i = 28; i >= 0; i -= 4) { + char c[2] = { hx[(n >> i) & 0xF], '\0' }; + sc_prt(c); + } +} + +static void sc_line(void) { + sc_prt("-------------------------------------\n"); +} + +static void sc_sep(const char* title) { + sc_prt("\n "); + sc_prt(title); + sc_prt("\n"); + sc_line(); +} + +/* ============================================================ + Issue Logging + ============================================================ */ + +static const char* severity_str(int sev) { + switch (sev) { + case SEC_OK: return "OK"; + case SEC_WARN: return "UYARI"; + case SEC_CRITICAL: return "KRITIK"; + case SEC_PANIC: return "PANIC"; + default: return "UNKNOWN"; + } +} + +void securchk_log_issue(securchk_severity_t severity, const char* module, const char* msg, uint32_t detail) { + sc_prt("[PSC] "); + sc_prt(severity_str(severity)); + sc_prt(" ["); + sc_prt(module); + sc_prt("] "); + sc_prt(msg); + if (detail != 0) { + sc_prt(" ("); + sc_prt_hex(detail); + sc_prt(")"); + } + sc_prt("\n"); +} + +/* ============================================================ + Stack Canary + ============================================================ */ + +void securchk_stack_canary_set(uint32_t* stack, uint32_t stack_size) { + if (!stack || stack_size < 8) return; + uint32_t words = stack_size / sizeof(uint32_t); + stack[0] = SECURCHK_STACK_CANARY; + stack[words - 1] = SECURCHK_STACK_CANARY; +} + +int securchk_stack_canary_check(uint32_t* stack, uint32_t stack_size) { + if (!stack || stack_size < 8) return 0; + uint32_t words = stack_size / sizeof(uint32_t); + if (stack[0] != SECURCHK_STACK_CANARY) return 0; + if (stack[words - 1] != SECURCHK_STACK_CANARY) return 0; + return 1; +} + +/* ============================================================ + 1. Task Integrity Check + - Task list circular reference dogrulanir + - NULL pointer / gecerli entry check + - Duplicate PID tespiti + - Gecerli state aralik kontrolu + ============================================================ */ + +int securchk_check_task_integrity(securchk_result_t* result) { + if (!result || !task_list) { + if (result) result->total_checks++; + return SEC_OK; + } + + int issues = 0; + uint32_t count = 0; + task_t* head = task_list; + task_t* cur = head; + + do { + if (!cur) { + securchk_log_issue(SEC_CRITICAL, "TASK", "Task listesinde NULL dugum", 0); + result->critical++; + issues++; + break; + } + + if (!cur->entry) { + securchk_log_issue(SEC_WARN, "TASK", "Gecersiz entry pointer, PID", cur->id); + result->warnings++; + issues++; + } + + if (!cur->stack || cur->stack_size == 0) { + securchk_log_issue(SEC_WARN, "TASK", "Gecersiz stack, PID", cur->id); + result->warnings++; + issues++; + } + + if ((int)cur->state < 0 || (int)cur->state > 3) { + securchk_log_issue(SEC_CRITICAL, "TASK", "Gecersiz task state, PID", cur->id); + result->critical++; + issues++; + } + + if (cur->id > SECURCHK_MAX_TASKS) { + securchk_log_issue(SEC_WARN, "TASK", "PID sinir asimi", cur->id); + result->warnings++; + issues++; + } + + count++; + cur = cur->next; + } while (cur && cur != head); + + if (count > SECURCHK_MAX_TASKS) { + securchk_log_issue(SEC_CRITICAL, "TASK", "Task sayisi sinir asimi", count); + result->critical++; + issues++; + } + + result->tasks_validated = count; + result->total_checks++; + + if (issues == 0) result->passed++; + return issues > 0 ? SEC_WARN : SEC_OK; +} + +/* ============================================================ + 2. Stack Overflow Check + - Her task icin stack canary kontrolu + - Stack pointer (esp) sinirlari disinda mi + ============================================================ */ + +int securchk_check_stack_overflow(securchk_result_t* result) { + if (!result || !task_list) { + if (result) result->total_checks++; + return SEC_OK; + } + + int issues = 0; + task_t* head = task_list; + task_t* cur = head; + + do { + if (!cur || !cur->stack || cur->stack_size == 0) { + cur = cur ? cur->next : NULL; + continue; + } + + uint32_t stack_base = (uint32_t)cur->stack; + uint32_t stack_top = stack_base + cur->stack_size; + + if (cur->esp < stack_base || cur->esp > stack_top) { + securchk_log_issue(SEC_CRITICAL, "STACK", "ESP stack sinirlari disinda, PID", cur->id); + result->stack_overflows++; + result->critical++; + issues++; + } + + if (cur->ebp < stack_base || cur->ebp > stack_top) { + securchk_log_issue(SEC_WARN, "STACK", "EBP stack sinirlari disinda, PID", cur->id); + result->warnings++; + issues++; + } + + cur = cur->next; + } while (cur && cur != head); + + result->total_checks++; + if (issues == 0) result->passed++; + return issues > 0 ? SEC_WARN : SEC_OK; +} + +/* ============================================================ + 3. Heap Integrity Check + - kmalloc/kfree tutarlilik + - Null pointer allocation denemeleri + - Heap buyukluk sinirlari + ============================================================ */ + +int securchk_check_heap_integrity(securchk_result_t* result) { + if (!result) return SEC_OK; + + int issues = 0; + result->total_checks++; + + void* test_alloc = kmalloc(16); + if (!test_alloc) { + securchk_log_issue(SEC_WARN, "HEAP", "kmalloc basarisiz (dusuk bellek)", 0); + result->warnings++; + issues++; + } else { + memset(test_alloc, 0xAA, 16); + uint8_t* buf = (uint8_t*)test_alloc; + int corrupt = 0; + for (int i = 0; i < 16; i++) { + if (buf[i] != 0xAA) { corrupt = 1; break; } + } + if (corrupt) { + securchk_log_issue(SEC_CRITICAL, "HEAP", "Heap bellek bozulmasi tespit edildi", 0); + result->heap_corruptions++; + result->critical++; + issues++; + } + kfree(test_alloc); + } + + if (issues == 0) result->passed++; + return issues > 0 ? SEC_WARN : SEC_OK; +} + +/* ============================================================ + 4. Syscall Bounds Check + - Syscall ID aralik kontrolu + - Gecersiz syscall denemeleri + ============================================================ */ + +int securchk_check_syscall_bounds(securchk_result_t* result) { + if (!result) return SEC_OK; + result->total_checks++; + + int ret = syscall(-1, NULL); + if (ret != -1) { + securchk_log_issue(SEC_CRITICAL, "SYSCALL", "Gecersiz syscall ID kabul edildi", 0); + result->syscall_violations++; + result->critical++; + } + + int ret2 = syscall(SECURCHK_MAX_SYSCALLS + 100, NULL); + if (ret2 != -1) { + securchk_log_issue(SEC_WARN, "SYSCALL", "Sinir asimi syscall ID kabul edildi", 0); + result->syscall_violations++; + result->warnings++; + } + + if (result->syscall_violations == 0) result->passed++; + return result->syscall_violations > 0 ? SEC_WARN : SEC_OK; +} + +/* ============================================================ + 5. Memory Safety Check + - memcpy/memset sifir boyut testi + - memcmp tutarlilik + - Pointer alignment + ============================================================ */ + +int securchk_check_memory_safety(securchk_result_t* result) { + if (!result) return SEC_OK; + result->total_checks++; + + int issues = 0; + char buf[64]; + + memset(buf, 0, sizeof(buf)); + if (buf[0] != 0 || buf[63] != 0) { + securchk_log_issue(SEC_CRITICAL, "MEM", "memset sifirlama hatasi", 0); + result->critical++; + issues++; + } + + memcpy(buf, "test_alignment_check", 22); + if (memcmp(buf, "test_alignment_check", 22) != 0) { + securchk_log_issue(SEC_CRITICAL, "MEM", "memcmp tutarsizlik", 0); + result->critical++; + issues++; + } + + if (((uint32_t)buf & 0x3) != 0) { + securchk_log_issue(SEC_WARN, "MEM", "Stack alignment hatasi", (uint32_t)buf); + result->warnings++; + issues++; + } + + if (issues == 0) result->passed++; + return issues > 0 ? SEC_WARN : SEC_OK; +} + +/* ============================================================ + 6. Driver State Check + - VGA driver durum kontrolu + - ATA/Storage erisim hazirlik + - Serial port hazirlik + ============================================================ */ + +int securchk_check_driver_state(securchk_result_t* result) { + if (!result) return SEC_OK; + result->total_checks++; + + int issues = 0; + + vga_clear_screen("C"); + vga_set_color_scheme(0x07, 0x00); + + securchk_log_issue(SEC_OK, "DRIVER", "VGA driver aktif", 0); + + return SEC_OK; +} + +/* ============================================================ + 7. Kernel Structure Check + - Kernel info tutarlilik + - Linker symbol sinirlari + - Paging/VMM yapisinin temel kontrolu + ============================================================ */ + +int securchk_check_kernel_structures(securchk_result_t* result) { + if (!result) return SEC_OK; + result->total_checks++; + + int issues = 0; + + if (PAGE_SIZE != 4096) { + securchk_log_issue(SEC_CRITICAL, "KERN", "PAGE_SIZE tutarsiz", PAGE_SIZE); + result->critical++; + issues++; + } + + if (sizeof(void*) != 4) { + securchk_log_issue(SEC_CRITICAL, "KERN", "Pointer boyutu 32-bit degil", sizeof(void*)); + result->critical++; + issues++; + } + + if (sizeof(uint32_t) != 4) { + securchk_log_issue(SEC_CRITICAL, "KERN", "uint32_t boyutu hatali", sizeof(uint32_t)); + result->critical++; + issues++; + } + + if (issues == 0) result->passed++; + return issues > 0 ? SEC_CRITICAL : SEC_OK; +} + +/* ============================================================ + Init + ============================================================ */ + +void securchk_init(void) { + g_initialized = 1; +} + +/* ============================================================ + Main Run + ============================================================ */ + +void securchk_run(securchk_result_t* result) { + if (!result) return; + + result->total_checks = 0; + result->passed = 0; + result->warnings = 0; + result->critical = 0; + result->tasks_validated = 0; + result->stack_overflows = 0; + result->heap_corruptions = 0; + result->syscall_violations = 0; + result->memory_leaks = 0; + + sc_line(); + sc_prt(" OpenKernel Security Checker (PSC)\n"); + sc_line(); + + sc_sep("Task Integrity"); + securchk_check_task_integrity(result); + + sc_sep("Stack Overflow"); + securchk_check_stack_overflow(result); + + sc_sep("Heap Integrity"); + securchk_check_heap_integrity(result); + + sc_sep("Syscall Bounds"); + securchk_check_syscall_bounds(result); + + sc_sep("Memory Safety"); + securchk_check_memory_safety(result); + + sc_sep("Driver State"); + securchk_check_driver_state(result); + + sc_sep("Kernel Structures"); + securchk_check_kernel_structures(result); + + securchk_print_result(result); +} + +/* ============================================================ + Result Print + ============================================================ */ + +void securchk_print_result(securchk_result_t* result) { + if (!result) return; + + sc_line(); + sc_prt(" Guvenlik Kontrolu Tamamlandi\n"); + sc_prt(" Toplam Kontrol : "); + sc_prt_dec(result->total_checks); + sc_prt("\n Gecen : "); + sc_prt_dec(result->passed); + sc_prt("\n Uyari : "); + sc_prt_dec(result->warnings); + sc_prt("\n Kritik : "); + sc_prt_dec(result->critical); + sc_prt("\n Task Dogrulandi: "); + sc_prt_dec(result->tasks_validated); + sc_prt("\n Stack Overflow : "); + sc_prt_dec(result->stack_overflows); + sc_prt("\n Heap Bozulma : "); + sc_prt_dec(result->heap_corruptions); + sc_prt("\n Syscall Ihlal : "); + sc_prt_dec(result->syscall_violations); + sc_prt("\n"); + sc_line(); +} + +int securchk_get_overall_status(securchk_result_t* result) { + if (!result) return -1; + if (result->critical > 0) return SEC_CRITICAL; + if (result->warnings > 0) return SEC_WARN; + return SEC_OK; +} From 60a8ad4df2b41a2e7cd22d473800d09b273b8666 Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:08:06 +0300 Subject: [PATCH 2/8] Add files via upload --- .../KernelServices/SecurityChecker/securchk.h | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Kernel/KernelServices/SecurityChecker/securchk.h diff --git a/Kernel/KernelServices/SecurityChecker/securchk.h b/Kernel/KernelServices/SecurityChecker/securchk.h new file mode 100644 index 0000000..dacdfd0 --- /dev/null +++ b/Kernel/KernelServices/SecurityChecker/securchk.h @@ -0,0 +1,60 @@ +#ifndef SECURCHK_H +#define SECURCHK_H + +#include + +#define SECURCHK_MAX_TASKS 256 +#define SECURCHK_MAX_SYSCALLS 32 +#define SECURCHK_STACK_CANARY 0xDEADBEEF +#define SECURCHK_HEAP_MAGIC 0xCAFEBABE + +typedef enum { + SEC_OK = 0, + SEC_WARN, + SEC_CRITICAL, + SEC_PANIC +} securchk_severity_t; + +typedef struct { + int severity; + const char* module; + const char* message; + uint32_t detail; +} securchk_issue_t; + +typedef struct { + uint32_t total_checks; + uint32_t passed; + uint32_t warnings; + uint32_t critical; + uint32_t tasks_validated; + uint32_t stack_overflows; + uint32_t heap_corruptions; + uint32_t syscall_violations; + uint32_t memory_leaks; +} securchk_result_t; + +void securchk_init(void); +void securchk_run(securchk_result_t* result); + +int securchk_check_task_integrity(securchk_result_t* result); +int securchk_check_stack_overflow(securchk_result_t* result); +int securchk_check_heap_integrity(securchk_result_t* result); +int securchk_check_syscall_bounds(securchk_result_t* result); +int securchk_check_memory_safety(securchk_result_t* result); +int securchk_check_driver_state(securchk_result_t* result); +int securchk_check_kernel_structures(securchk_result_t* result); + +void securchk_print_result(securchk_result_t* result); +void securchk_log_issue(securchk_severity_t severity, const char* module, const char* msg, uint32_t detail); +int securchk_get_overall_status(securchk_result_t* result); + +void securchk_stack_canary_set(uint32_t* stack, uint32_t stack_size); +int securchk_stack_canary_check(uint32_t* stack, uint32_t stack_size); + +#define SECURCHK_MODULE_NAME "Security Checker" +#define SECURCHK_MODULE_DESC "Kernel Security Checker for OpenKernel" +#define SECURCHK_MODULE_VER "1.0" +#define SECURCHK_MODULE_AUTHOR "OpenSoftware-World" + +#endif From aba82bfb715dffc7d2f3bf28a538533fa056f7d1 Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:09:01 +0300 Subject: [PATCH 3/8] Enhance syscall handler with security check cases --- SystemLib/SysCalls/syscall.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/SystemLib/SysCalls/syscall.c b/SystemLib/SysCalls/syscall.c index e1090c1..921d788 100644 --- a/SystemLib/SysCalls/syscall.c +++ b/SystemLib/SysCalls/syscall.c @@ -1,24 +1,51 @@ #include "syscall.h" +static securchk_result_t g_sec_result; +static int g_sec_initialized = 0; + int syscall(int id, void* arg) { return syscall_handler(id, arg); } int syscall_handler(int id, void* arg) { - switch(id) - { + switch (id) { case SYSCALL_PRINT: + if (!arg) return -1; vga_print_scr((char*)arg); return 0; + case SYSCALL_CLEAR_SCREEN: vga_clear_screen("C"); return 0; + case SYSCALL_SHUTDOWN: sys_next_status("S", 0); return 0; + case SYSCALL_REBOOT: sys_next_status("R", 0); return 0; + + case SYSCALL_SECURCHK_INIT: + securchk_init(); + g_sec_initialized = 1; + return 0; + + case SYSCALL_SECURCHK_RUN: + if (!g_sec_initialized) securchk_init(); + if (arg) + securchk_run((securchk_result_t*)arg); + else + securchk_run(&g_sec_result); + return 0; + + case SYSCALL_SECURCHK_STATUS: + if (!g_sec_initialized) return -1; + if (arg) + *(securchk_result_t*)arg = g_sec_result; + return securchk_get_overall_status(&g_sec_result); + + default: + return -1; } - return -1; -} \ No newline at end of file +} From 5ac04dd37ccd34529f09ce664eb1a86ed865c35d Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:09:14 +0300 Subject: [PATCH 4/8] Add security checker system calls to syscall.h --- SystemLib/SysCalls/syscall.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/SystemLib/SysCalls/syscall.h b/SystemLib/SysCalls/syscall.h index 1c46efe..3fd91ef 100644 --- a/SystemLib/SysCalls/syscall.h +++ b/SystemLib/SysCalls/syscall.h @@ -3,11 +3,16 @@ #include #include +#include -#define SYSCALL_PRINT 0 -#define SYSCALL_CLEAR_SCREEN 1 -#define SYSCALL_SHUTDOWN 2 -#define SYSCALL_REBOOT 3 +#define SYSCALL_PRINT 0 +#define SYSCALL_CLEAR_SCREEN 1 +#define SYSCALL_SHUTDOWN 2 +#define SYSCALL_REBOOT 3 +#define SYSCALL_SECURCHK_INIT 4 +#define SYSCALL_SECURCHK_RUN 5 +#define SYSCALL_SECURCHK_STATUS 6 +#define SYSCALL_MAX_ID 31 int syscall(int id, void* arg); int syscall_handler(int id, void* arg); @@ -19,4 +24,4 @@ int syscall_handler(int id, void* arg); #define SYSCALL_MODULE_FILE_NAME "syscall.lib" #define SYSCALL_MODULE_KRNL_VER "2.0" -#endif \ No newline at end of file +#endif From 5190cc2f5eea3ea03000fbfd3518549f66479e2f Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:10:22 +0300 Subject: [PATCH 5/8] Enhance CFLAGS with additional compiler options --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 716a8e3..d52e949 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ KERNEL = $(BUILD)/os.bin ISOFILE = your_os.iso # Compile Tools -CFLAGS = -m32 -ffreestanding -O2 -Wall -Wextra -I . +CFLAGS = -m32 -ffreestanding -O2 -Wall -Wextra -Werror -fstack-protector -I . LDFLAGS = -m elf_i386 -T link.ld # Source Files @@ -42,6 +42,7 @@ C_SRC = OpenKernel/Drivers/Vga/vga.c \ OpenKernel/Kernel/ErrorHandler/panic.c \ OpenKernel/Kernel/KernelServices/LogService/log.c \ OpenKernel/Kernel/KernelServices/VirtualMem/vmem.c \ + OpenKernel/Kernel/KernelServices/SecurityChecker/securchk.c \ OpenKernel/SystemLib/TaskMng/task.c \ OpenKernel/SystemLib/TypeConversion/type_conv.c @@ -93,4 +94,4 @@ run: iso # Clean clean: - rm -rf $(BUILD) $(ISO) $(ISOFILE) \ No newline at end of file + rm -rf $(BUILD) $(ISO) $(ISOFILE) From 431f7fb5ec8e059a22802a1cf5f8d06d5bafeb0d Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:11:48 +0300 Subject: [PATCH 6/8] Implement AHCI driver with port management functions This file implements the AHCI driver, including functions for initializing the driver, scanning for ports, reading and writing sectors, and printing port information. --- Drivers/AHCI/ahci.c | 342 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 Drivers/AHCI/ahci.c diff --git a/Drivers/AHCI/ahci.c b/Drivers/AHCI/ahci.c new file mode 100644 index 0000000..5ac9e75 --- /dev/null +++ b/Drivers/AHCI/ahci.c @@ -0,0 +1,342 @@ +#include "ahci.h" + +#include +#include +#include + +/* ============================================================ + Internal State + ============================================================ */ + +static ahci_hba_mem_t* hba_mem = NULL; +static ahci_port_state_t ports[AHCI_MAX_PORTS]; +static int port_count = 0; + +/* ============================================================ + Helper: print hex value + ============================================================ */ + +static void prt_hex(uint32_t val) { + const char* hx = "0123456789ABCDEF"; + vga_print_scr_nw("0x"); + for (int i = 28; i >= 0; i -= 4) { + char c[2] = { hx[(val >> i) & 0xF], '\0' }; + vga_print_scr_nw(c); + } +} + +static void prt_dec(uint32_t val) { + char buf[12]; + int i = 0; + if (val == 0) { buf[i++] = '0'; } + else { + char t[12]; int ti = 0; + while (val > 0) { t[ti++] = (val % 10) + '0'; val /= 10; } + while (ti > 0) buf[i++] = t[--ti]; + } + buf[i] = '\0'; + vga_print_scr_nw(buf); +} + +/* ============================================================ + HBA Port Start + ============================================================ */ + +static void port_start(ahci_port_t* port) { + while (port->cmd & (AHCI_PORT_CMD_CRA | AHCI_PORT_CMD_FR)) + ; + + port->cmd &= ~AHCI_PORT_CMD_ST; + port->cmd &= ~AHCI_PORT_CMD_FRE; + + while (port->cmd & AHCI_PORT_CMD_FR) + ; + + port->cmd |= AHCI_PORT_CMD_FRE; + port->cmd |= AHCI_PORT_CMD_ST; +} + +/* ============================================================ + HBA Port Stop + ============================================================ */ + +static void port_stop(ahci_port_t* port) { + port->cmd &= ~AHCI_PORT_CMD_ST; + port->cmd &= ~AHCI_PORT_CMD_FRE; +} + +/* ============================================================ + Find Command Slot (wait for empty slot) + ============================================================ */ + +static int find_cmdslot(ahci_port_t* port) { + uint32_t slots = (port->sact | port->ci); + for (int i = 0; i < AHCI_MAX_SLOTS; i++) { + if (!(slots & (1 << i))) return i; + } + return -1; +} + +/* ============================================================ + Configure Command Header / PRDT for a port + ============================================================ */ + +static int configure_port(ahci_port_state_t* ps) { + ahci_port_t* port = ps->port; + + /* Stop port before reconfiguration */ + port_stop(port); + + /* Allocate command list (1K aligned, 32 entries * 32 bytes = 1024) */ + uint32_t clb_sz = 1024; + void* clb = kmalloc(clb_sz); + if (!clb) return -1; + memset(clb, 0, clb_sz); + + /* Allocate received FIS (256 bytes, aligned) */ + uint32_t fis_sz = 256; + void* fis = kmalloc(fis_sz); + if (!fis) { kfree(clb); return -1; } + memset(fis, 0, fis_sz); + + /* Allocate command table (aligned, 1024 bytes per entry) */ + ps->cmd_table = (ahci_cmd_table_t*)kmalloc( + sizeof(ahci_cmd_table_t) * AHCI_MAX_SLOTS); + if (!ps->cmd_table) { + kfree(clb); kfree(fis); return -1; + } + memset(ps->cmd_table, 0, sizeof(ahci_cmd_table_t) * AHCI_MAX_SLOTS); + + /* Set CLB and FIS addresses in port registers */ + port->clb = (uint32_t)(uint64_t)clb; + port->clbu = (uint32_t)((uint64_t)clb >> 32); + port->fb = (uint32_t)(uint64_t)fis; + port->fbu = (uint32_t)((uint64_t)fis >> 32); + + /* Initialize command headers to point to their tables */ + ahci_cmd_hdr_t* hdr = (ahci_cmd_hdr_t*)clb; + for (int i = 0; i < AHCI_MAX_SLOTS; i++) { + hdr[i].dw0 = 0; + hdr[i].desc_base = (uint32_t)(uint64_t)&ps->cmd_table[i]; + hdr[i].desc_base_upper = (uint32_t)((uint64_t)&ps->cmd_table[i] >> 32); + hdr[i].rsv0 = 0; + } + + ps->rx_fis = fis; + port_start(port); + return 0; +} + +/* ============================================================ + Read/Write a single sector using AHCI + ============================================================ */ + +static int ahci_rw(int port_num, uint32_t lba, uint32_t count, + uint8_t* buf, int write) { + if (port_num < 0 || port_num >= port_count) return -1; + ahci_port_state_t* ps = &ports[port_num]; + ahci_port_t* port = ps->port; + + int slot = find_cmdslot(port); + if (slot < 0) return -1; + + ahci_cmd_hdr_t* cmd_hdr = (ahci_cmd_hdr_t*)(uint64_t)port->clb; + cmd_hdr[slot].dw0 = 0; + + /* PRD table: single entry for this buffer */ + ahci_cmd_table_t* cmd_tbl = &ps->cmd_table[slot]; + ahci_prdt_entry_t* prdt = &cmd_tbl->prdt[0]; + prdt->dba = (uint32_t)(uint64_t)buf; + prdt->dbau = (uint32_t)((uint64_t)buf >> 32); + prdt->dbc = (count * ps->sector_size) - 1; + prdt->i = 1; + + /* FIS: Register H2D */ + ahci_fis_reg_h2d_t* fis = (ahci_fis_reg_h2d_t*)cmd_tbl->cfis; + memset(cmd_tbl->cfis, 0, 64); + fis->fis_type = FIS_TYPE_REG_H2D; + fis->c = 1; + fis->cmd = write ? 0x35 : 0x25; /* WRITE DMA EXT / READ DMA EXT */ + fis->lba0 = lba & 0xFF; + fis->lba1 = (lba >> 8) & 0xFF; + fis->lba2 = (lba >> 16) & 0xFF; + fis->lba3 = (lba >> 24) & 0xFF; + fis->device = 1 << 6; /* LBA mode */ + fis->countl = count & 0xFF; + fis->counth = (count >> 8) & 0xFF; + + /* Command header setup */ + cmd_hdr[slot].dw0 = (AHCI_CMD_CFIS_LEN & 0x1F); + cmd_hdr[slot].dw0 |= (write ? AHCI_CMD_WRITE : 0); + cmd_hdr[slot].dw0 |= AHCI_CMD_PREF; + cmd_hdr[slot].dw0 |= 1; /* 1 PRDT entry */ + + /* Issue command */ + port->is = (uint32_t)-1; + port->ci = (1 << slot); + + /* Wait for completion */ + uint32_t timeout = 1000000; + while (timeout--) { + if (!(port->ci & (1 << slot))) break; + if (port->is & AHCI_PORT_IS_TFES) { + return -1; /* Task File Error */ + } + for (volatile int j = 0; j < 100; j++) ; + } + if (timeout == 0) return -1; + + return 0; +} + +/* ============================================================ + Public: Scan for AHCI controllers via PCI + ============================================================ */ + +int ahci_scan_ports(void) { + port_count = 0; + + if (!hba_mem) return -1; + + uint32_t pi = hba_mem->pi; + for (int i = 0; i < AHCI_MAX_PORTS; i++) { + if (!(pi & (1 << i))) continue; + + ahci_port_t* p = (ahci_port_t*)&hba_mem->ports_data[i * AHCI_PORT_SIZE]; + + uint32_t sig = p->sig; + int type = 0; + + if (sig == AHCI_SIG_ATA) type = 1; /* SATA */ + else if (sig == AHCI_SIG_ATAPI) type = 2; /* ATAPI */ + else if (sig == AHCI_SIG_PM) type = 3; /* Port Multiplier */ + else if (sig == AHCI_SIG_SEMB) type = 4; /* SEMB */ + else continue; + + if (type != 1) continue; /* Only SATA disks for now */ + + ports[port_count].port = p; + ports[port_count].port_num = i; + ports[port_count].type = type; + ports[port_count].present = 1; + ports[port_count].sector_size = 512; + + /* Identify device to get total sectors */ + uint8_t id_buf[512]; + if (ahci_rw(port_count, 0, 1, id_buf, 0) == 0) { + uint16_t* id = (uint16_t*)id_buf; + uint32_t lba28 = (uint32_t)id[60] | ((uint32_t)id[61] << 16); + ports[port_count].total_sectors = lba28; + } else { + ports[port_count].total_sectors = 0; + } + + if (configure_port(&ports[port_count]) != 0) { + ports[port_count].present = 0; + continue; + } + + port_count++; + } + + return port_count; +} + +/* ============================================================ + Public: Initialize AHCI driver + ============================================================ */ + +int ahci_init(void) { + /* Find AHCI controller via PCI */ + pci_dev_t* dev = NULL; + uint32_t abar = 0; + + for (int i = 0; i < pci_get_dev_count(); i++) { + dev = pci_get_device(i); + if (!dev) continue; + if (dev->class_mod == AHCI_PCI_CLASS && + dev->subclass == AHCI_PCI_SUBCLASS && + dev->prog_if == AHCI_PCI_PROGIF) { + break; + } + dev = NULL; + } + + if (!dev) { + vga_print_scr_nw("[AHCI] No AHCI controller found via PCI\n"); + return -1; + } + + /* Read BAR5 (ABAR) */ + abar = pci_read(dev->bus, dev->dev, dev->func, 0x24); + abar &= 0xFFFFFFF0; /* Lower 4 bits are flags */ + + if (abar == 0) { + vga_print_scr_nw("[AHCI] Invalid ABAR address\n"); + return -1; + } + + hba_mem = (ahci_hba_mem_t*)(uint64_t)abar; + + /* Enable AHCI mode */ + hba_mem->ghc |= AHCI_GHC_AE; + + vga_print_scr_nw("[AHCI] Controller found at ABAR: "); + prt_hex(abar); + vga_print_scr_nw(" | Cap: "); + prt_hex(hba_mem->cap); + vga_print_scr_nw(" | Version: "); + prt_hex(hba_mem->vs); + vga_print_scr_nw("\n"); + + return 0; +} + +/* ============================================================ + Public: Read sectors + ============================================================ */ + +void ahci_read_sector(int port, uint32_t lba, uint32_t count, uint8_t* buf) { + ahci_rw(port, lba, count, buf, 0); +} + +/* ============================================================ + Public: Write sectors + ============================================================ */ + +void ahci_write_sector(int port, uint32_t lba, uint32_t count, const uint8_t* buf) { + ahci_rw(port, lba, count, (uint8_t*)buf, 1); +} + +/* ============================================================ + Public: Get port info + ============================================================ */ + +int ahci_get_port_count(void) { + return port_count; +} + +ahci_port_state_t* ahci_get_port(int index) { + if (index < 0 || index >= port_count) return NULL; + return &ports[index]; +} + +/* ============================================================ + Public: Print AHCI info + ============================================================ */ + +void ahci_print_info(void) { + vga_print_scr_nw("\n[AHCI] Ports found: "); + prt_dec(port_count); + vga_print_scr_nw("\n"); + + for (int i = 0; i < port_count; i++) { + vga_print_scr_nw(" Port "); + prt_dec(ports[i].port_num); + vga_print_scr_nw(": "); + prt_dec(ports[i].total_sectors); + vga_print_scr_nw(" sectors ("); + prt_dec(ports[i].total_sectors / 2048); + vga_print_scr_nw(" MB)\n"); + } +} From 26c4df5bc0437d7999d82a1a7c9556cba6303310 Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:12:14 +0300 Subject: [PATCH 7/8] Add AHCI header file with register definitions --- Drivers/AHCI/ahci.h | 222 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 Drivers/AHCI/ahci.h diff --git a/Drivers/AHCI/ahci.h b/Drivers/AHCI/ahci.h new file mode 100644 index 0000000..5653c31 --- /dev/null +++ b/Drivers/AHCI/ahci.h @@ -0,0 +1,222 @@ +#ifndef AHCI_H +#define AHCI_H + +#include +#include + +/* ============================================================ + AHCI Register Offsets (from ABAR) + ============================================================ */ + +#define AHCI_CAP 0x00 /* Host Capabilities */ +#define AHCI_GHC 0x04 /* Global Host Control */ +#define AHCI_IS 0x08 /* Interrupt Status */ +#define AHCI_PI 0x0C /* Ports Implemented */ +#define AHCI_VS 0x10 /* Version */ +#define AHCI_AHCICTL 0x24 /* AHCI Control */ + +#define AHCI_PORT_SIZE 0x80 +#define AHCI_PORT_BASE 0x100 + +/* Port Registers */ +#define PORT_CLB 0x00 /* Command List Base */ +#define PORT_CLBU 0x04 /* Command List Base Upper */ +#define PORT_FB 0x08 /* FIS Base */ +#define PORT_FBU 0x0C /* FIS Base Upper */ +#define PORT_IS 0x10 /* Interrupt Status */ +#define PORT_IE 0x14 /* Interrupt Enable */ +#define PORT_CMD 0x18 /* Command and Status */ +#define PORT_TFD 0x20 /* Task File Data */ +#define PORT_SIG 0x24 /* Signature */ +#define PORT_SSTS 0x28 /* SATA Status */ +#define PORT_SCTL 0x2C /* SATA Control */ +#define PORT_SERR 0x30 /* SATA Error */ +#define PORT_SACT 0x34 /* SATA Active */ +#define PORT_CI 0x38 /* Command Issue */ +#define PORT_SNTF 0x3C /* SATA Notification */ +#define PORT_FBS 0x40 /* FIS-based Switching */ + +/* PCI IDs */ +#define AHCI_PCI_CLASS 0x01 +#define AHCI_PCI_SUBCLASS 0x06 +#define AHCI_PCI_PROGIF 0x01 + +#define AHCI_PCI_VID_INTEL 0x8086 + +/* AHCI Flags */ +#define AHCI_GHC_AE (1 << 31) /* AHCI Enable */ +#define AHCI_GHC_IE (1 << 1) /* Interrupt Enable */ +#define AHCI_GHC_HR (1 << 0) /* HBA Reset */ + +#define AHCI_PORT_CMD_ST (1 << 0) /* Start */ +#define AHCI_PORT_CMD_FRE (1 << 4) /* FIS Receive Enable */ +#define AHCI_PORT_CMD_CRA (1 << 31) /* Command List Running */ +#define AHCI_PORT_CMD_FR (1 << 14) /* FIS Receive Running */ + +#define AHCI_PORT_IS_TFES (1 << 30) /* Task File Error Status */ +#define AHCI_PORT_IS_DHRS (1 << 0) /* Device to Host Register FIS */ +#define AHCI_PORT_IS_PSS (1 << 27) /* Set Task Bits */ + +#define AHCI_SIG_ATA 0x00000101 +#define AHCI_SIG_ATAPI 0xEB140101 +#define AHCI_SIG_PM 0x96690101 +#define AHCI_SIG_SEMB 0xC33C0101 + +#define AHCI_CMD_CFIS_LEN 0x10 /* 16 DWORDs */ +#define AHCI_CMD_ACMD 0x0040 +#define AHCI_CMD_WRITE 0x0040 +#define AHCI_CMD_PREF 0x0004 +#define AHCI_CMD_CLEAR 0x0001 + +/* FIS Types */ +#define FIS_TYPE_REG_H2D 0x27 +#define FIS_TYPE_REG_D2H 0x34 +#define FIS_TYPE_DMA_ACT 0x39 +#define FIS_TYPE_DMA_SETUP 0x41 +#define FIS_TYPE_DATA 0x46 +#define FIS_TYPE_BIST 0x58 +#define FIS_TYPE_PIO_SETUP 0x5F +#define FIS_TYPE_DEV_BITS 0xA1 + +#define AHCI_MAX_PORTS 32 +#define AHCI_MAX_SLOTS 32 +#define AHCI_MAX_PRDT 8 +#define AHCI_PRDT_MAX_SZ (4 * 1024 * 1024) /* 4MB */ + +/* ============================================================ + AHCI Structures + ============================================================ */ + +typedef volatile struct { + uint32_t cap; + uint32_t ghc; + uint32_t is; + uint32_t pi; + uint32_t vs; + uint32_t ccc_ctl; + uint32_t ccc_ports; + uint32_t em_loc; + uint32_t em_ctl; + uint32_t cap2; + uint32_t bohc; + uint8_t reserved[0x60]; + uint8_t vendor[0x60]; + uint8_t ports_data[0x80 * 32]; +} __attribute__((packed)) ahci_hba_mem_t; + +typedef volatile struct { + uint32_t clb; + uint32_t clbu; + uint32_t fb; + uint32_t fbu; + uint32_t is; + uint32_t ie; + uint32_t cmd; + uint32_t rsv0; + uint32_t tfd; + uint32_t sig; + uint32_t ssts; + uint32_t sctl; + uint32_t serr; + uint32_t sact; + uint32_t ci; + uint32_t sntf; + uint32_t fbs; + uint32_t rsv1[11]; + uint32_t vendor[4]; +} __attribute__((packed)) ahci_port_t; + +typedef struct { + uint32_t dw0; + uint32_t desc_base; + uint32_t desc_base_upper; + uint32_t rsv0; +} __attribute__((packed)) ahci_cmd_hdr_t; + +typedef struct { + uint8_t cfis[64]; + uint8_t acmd[16]; + uint8_t rsv0[48]; + uint8_t prdt[128 * AHCI_MAX_PRDT]; +} __attribute__((packed)) ahci_cmd_table_t; + +typedef struct { + uint32_t dba; + uint32_t dbau; + uint32_t rsv0; + uint32_t dbc: 22; + uint32_t rsv1: 9; + uint32_t i: 1; +} __attribute__((packed)) ahci_prdt_entry_t; + +typedef struct { + uint8_t fis_type; + uint8_t pmport: 4; + uint8_t rsv0: 3; + uint8_t c: 1; + uint8_t cmd; + uint8_t featurel; + uint8_t lba0; + uint8_t lba1; + uint8_t lba2; + uint8_t device; + uint8_t lba3; + uint8_t lba4; + uint8_t lba5; + uint8_t featureh; + uint8_t countl; + uint8_t counth; + uint8_t icc; + uint8_t control; + uint8_t rsv1[4]; +} __attribute__((packed)) ahci_fis_reg_h2d_t; + +typedef struct { + uint8_t fis_type; + uint8_t pmport: 4; + uint8_t rsv0: 2; + uint8_t i: 1; + uint8_t c: 1; + uint8_t status; + uint8_t error; + uint8_t lba0; + uint8_t lba1; + uint8_t lba2; + uint8_t device; + uint8_t lba3; + uint8_t lba4; + uint8_t lba5; + uint8_t rsv1[2]; + uint8_t countl; + uint8_t counth; + uint8_t rsv2[10]; +} __attribute__((packed)) ahci_fis_reg_d2h_t; + +/* Port state for driver */ +typedef struct { + ahci_port_t* port; + int port_num; + int type; + int present; + uint64_t total_sectors; + uint32_t sector_size; + ahci_cmd_table_t* cmd_table; + void* rx_fis; +} ahci_port_state_t; + +/* Driver public API */ +int ahci_init(void); +int ahci_scan_ports(void); +void ahci_read_sector(int port, uint32_t lba, uint32_t count, uint8_t* buf); +void ahci_write_sector(int port, uint32_t lba, uint32_t count, const uint8_t* buf); +int ahci_get_port_count(void); +ahci_port_state_t* ahci_get_port(int index); +void ahci_print_info(void); + +#define AHCI_DRIVER_NAME "OpenKernel AHCI SATA Driver" +#define AHCI_DRIVER_VER "1.0" +#define AHCI_DRIVER_DESC "AHCI SATA controller driver for OpenKernel" +#define AHCI_DRIVER_AUTHOR "OpenSoftware-World" +#define AHCI_DRIVER_KRNL_VER "2.0" + +#endif From 8dad93f9ce1346f69a644d2a0a92fd38bea3366b Mon Sep 17 00:00:00 2001 From: Mehmet Demir Date: Sat, 2 May 2026 17:12:48 +0300 Subject: [PATCH 8/8] Add AHCI driver source file to Makefile --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d52e949..64b4c8a 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ ASM_SRC = # Bootloader and assembly files C_SRC = OpenKernel/Drivers/Vga/vga.c \ OpenKernel/Drivers/Cpu/cpu.c \ OpenKernel/OFS/ofs.c \ + OpenKernel/Drivers/AHCI/ahci.c \ OpenKernel/Drivers/Ata/ata.c \ OpenKernel/SystemLib/Memory/mem.c \ OpenKernel/Drivers/Mouse/mouse.c \