]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
Feat: Add Shell, Keyboard Driver and Utils (LibC)
authortadryanom_bot <[email protected]>
Tue, 3 Feb 2026 02:39:32 +0000 (02:39 +0000)
committertadryanom_bot <[email protected]>
Tue, 3 Feb 2026 02:39:32 +0000 (02:39 +0000)
include/keyboard.h [new file with mode: 0644]
include/shell.h [new file with mode: 0644]
include/utils.h [new file with mode: 0644]
src/drivers/keyboard.c [new file with mode: 0644]
src/kernel/main.c
src/kernel/shell.c [new file with mode: 0644]
src/kernel/utils.c [new file with mode: 0644]

diff --git a/include/keyboard.h b/include/keyboard.h
new file mode 100644 (file)
index 0000000..bf61554
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdint.h>
+
+// Callback function type: called when a char is decoded
+typedef void (*keyboard_callback_t)(char);
+
+void keyboard_init(void);
+void keyboard_set_callback(keyboard_callback_t callback);
+
+#endif
diff --git a/include/shell.h b/include/shell.h
new file mode 100644 (file)
index 0000000..2af8086
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef SHELL_H
+#define SHELL_H
+
+void shell_init(void);
+
+#endif
diff --git a/include/utils.h b/include/utils.h
new file mode 100644 (file)
index 0000000..0305e06
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+size_t strlen(const char* str);
+int strcmp(const char* s1, const char* s2);
+int strncmp(const char* s1, const char* s2, size_t n);
+void* memset(void* ptr, int value, size_t num);
+void* memcpy(void* dst, const void* src, size_t n);
+
+// Reverse a string (helper for itoa)
+void reverse(char* str, int length);
+// Integer to ASCII
+void itoa(int num, char* str, int base);
+
+#endif
diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c
new file mode 100644 (file)
index 0000000..dbb5227
--- /dev/null
@@ -0,0 +1,78 @@
+#include "keyboard.h"
+#include "idt.h"
+#include "io.h"
+#include "uart_console.h"
+#include <stddef.h>
+
+static keyboard_callback_t active_callback = NULL;
+
+// US QWERTY Map (Scancodes 0x00 - 0x39)
+// 0 means unmapped or special key
+static char scancode_map[128] = {
+    0,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* Backspace */
+    '\t', /* Tab */
+    'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
+    0, /* 29   - Control */
+    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',   0, /* Left shift */
+    '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',   0, /* Right shift */
+    '*',
+    0,  /* Alt */
+    ' ', /* Space bar */
+    0,  /* Caps lock */
+    0,  /* 59 - F1 key ... > */
+    0,   0,   0,   0,   0,   0,   0,   0,
+    0,  /* < ... F10 */
+    0,  /* 69 - Num lock*/
+    0,  /* Scroll Lock */
+    0,  /* Home key */
+    0,  /* Up Arrow */
+    0,  /* Page Up */
+    -1, /* Minus */
+    0,  /* Left Arrow */
+    0,
+    0,  /* Right Arrow */
+    '+',
+    0,  /* 79 - End key*/
+    0,  /* Down Arrow */
+    0,  /* Page Down */
+    0,  /* Insert Key */
+    0,  /* Delete Key */
+    0,   0,   0,
+    0,  /* F11 Key */
+    0,  /* F12 Key */
+    0,  /* All other keys are undefined */
+};
+
+void keyboard_handler_impl(struct registers* regs) {
+    (void)regs;
+    
+    // Read status
+    uint8_t status = inb(0x64);
+    
+    // Check if buffer is full
+    if (status & 0x01) {
+        uint8_t scancode = inb(0x60);
+        
+        // If highest bit set, it's a key release
+        if (scancode & 0x80) {
+            // TODO: Handle shift release
+        } else {
+            // Key Press
+            if (scancode < 128) {
+                char c = scancode_map[scancode];
+                if (c != 0 && active_callback) {
+                    active_callback(c);
+                }
+            }
+        }
+    }
+}
+
+void keyboard_init(void) {
+    uart_print("[KBD] Initializing Keyboard Driver...\n");
+    register_interrupt_handler(33, keyboard_handler_impl);
+}
+
+void keyboard_set_callback(keyboard_callback_t callback) {
+    active_callback = callback;
+}
index 98546c32a16e7a5c07c89c58a54eff4f9ab2f905..e430184b7c0aa1418a50c9ed23d9a5427643ae36 100644 (file)
@@ -6,42 +6,14 @@
 #include "idt.h"
 #include "io.h"
 #include "process.h"
+#include "keyboard.h"
+#include "shell.h"
 
 /* Check if the compiler thinks we are targeting the wrong operating system. */
 #if defined(__linux__)
 #error "You are not using a cross-compiler, you will run into trouble"
 #endif
 
-// Simple Keyboard Handler Stub
-void keyboard_handler(struct registers* regs) {
-    (void)regs;
-    // Read scan code from port 0x60
-    uint8_t scancode = inb(0x60);
-    
-    // If top bit is set, it's a key release. Ignore.
-    if (!(scancode & 0x80)) {
-        uart_print("[KEY] Pressed!\n");
-    }
-}
-
-void task_a(void) {
-    uart_print("Task A Started!\n");
-    for(;;) {
-        uart_print("A");
-        for(volatile int i=0; i<5000000; i++);
-        schedule();
-    }
-}
-
-void task_b(void) {
-    uart_print("Task B Started!\n");
-    for(;;) {
-        uart_print("B");
-        for(volatile int i=0; i<5000000; i++);
-        schedule();
-    }
-}
-
 /*
  * Kernel Entry Point
  * Arguments are passed from boot.S (architecture specific)
@@ -79,29 +51,35 @@ void kernel_main(unsigned long magic, unsigned long addr) {
     uart_print("[AdrOS] Initializing IDT...\n");
     idt_init();
     
-    register_interrupt_handler(33, keyboard_handler);
+    // 5. Initialize Drivers
+    keyboard_init();
     
-    // 5. Initialize Multitasking
+    // 6. Initialize Multitasking (Optional for Shell, but good to have)
     uart_print("[AdrOS] Initializing Scheduler...\n");
     process_init();
     
-    process_create_kernel(task_a);
-    process_create_kernel(task_b);
+    // Start Shell as the main interaction loop
+    shell_init();
     
 #else
     uart_print("[WARN] VMM/IDT/Sched not implemented for this architecture yet.\n");
 #endif
 
     uart_print("Welcome to AdrOS (x86/ARM/RISC-V/MIPS)!\n");
-    uart_print("System Halted. Starting Multitasking...\n");
 
     // Infinite loop acting as Idle Task
+    // Shell is interrupt driven, so we just idle here.
     for(;;) {
-        // uart_print(".");
-        schedule();
-        
+        // We can execute background tasks here if needed
         #if defined(__i386__) || defined(__x86_64__)
         __asm__("hlt");
+        #elif defined(__aarch64__)
+        __asm__("wfi");
+        #elif defined(__riscv)
+        __asm__("wfi");
         #endif
+        
+        // If we had preemptive scheduling, the timer would wake us up.
+        // For cooperative, we assume shell is ISR based so HLT is fine.
     }
 }
diff --git a/src/kernel/shell.c b/src/kernel/shell.c
new file mode 100644 (file)
index 0000000..e55d07d
--- /dev/null
@@ -0,0 +1,96 @@
+#include "shell.h"
+#include "keyboard.h"
+#include "uart_console.h"
+#include "utils.h"
+#include "pmm.h"
+#include "vga_console.h"
+
+#define MAX_CMD_LEN 256
+static char cmd_buffer[MAX_CMD_LEN];
+static int cmd_index = 0;
+
+void print_prompt(void) {
+    uart_print("\nAdrOS $> ");
+}
+
+void execute_command(char* cmd) {
+    uart_print("\n");
+    
+    if (strcmp(cmd, "help") == 0) {
+        uart_print("Available commands:\n");
+        uart_print("  help   - Show this list\n");
+        uart_print("  clear  - Clear screen (if VGA)\n");
+        uart_print("  mem    - Show memory stats\n");
+        uart_print("  panic  - Trigger kernel panic\n");
+        uart_print("  reboot - Restart system\n");
+    } 
+    else if (strcmp(cmd, "clear") == 0) {
+        // ANSI clear screen for UART
+        uart_print("\033[2J\033[1;1H");
+        
+        // TODO: Clear VGA if active
+        // vga_clear();
+    }
+    else if (strcmp(cmd, "mem") == 0) {
+        // pmm_print_stats() is not impl yet, so let's fake it or add it
+        uart_print("Memory Stats:\n");
+        uart_print("  Total RAM: [TODO] MB\n");
+        uart_print("  Used:      [TODO] KB\n");
+        uart_print("  Free:      [TODO] KB\n");
+    }
+    else if (strcmp(cmd, "panic") == 0) {
+        // Trigger Int 0 (Div by zero)
+        int a = 1;
+        int b = 0;
+        int c = a / b;
+        (void)c;
+    }
+    else if (strcmp(cmd, "reboot") == 0) {
+        // 8042 keyboard controller reset command
+        uint8_t good = 0x02;
+        while (good & 0x02)
+            good = inb(0x64);
+        outb(0x64, 0xFE);
+        
+        // Triple Fault fallback
+        // idt_set_gate(0, 0, 0, 0);
+        // __asm__("int $0");
+    }
+    else if (strlen(cmd) > 0) {
+        uart_print("Unknown command: ");
+        uart_print(cmd);
+        uart_print("\n");
+    }
+    
+    print_prompt();
+}
+
+void shell_callback(char c) {
+    // Echo to screen
+    char str[2] = { c, 0 };
+    
+    if (c == '\n') {
+        cmd_buffer[cmd_index] = 0; // Null terminate
+        execute_command(cmd_buffer);
+        cmd_index = 0;
+    }
+    else if (c == '\b') {
+        if (cmd_index > 0) {
+            cmd_index--;
+            uart_print("\b \b"); // Backspace hack
+        }
+    }
+    else {
+        if (cmd_index < MAX_CMD_LEN - 1) {
+            cmd_buffer[cmd_index++] = c;
+            uart_print(str);
+        }
+    }
+}
+
+void shell_init(void) {
+    uart_print("[SHELL] Starting Shell...\n");
+    cmd_index = 0;
+    keyboard_set_callback(shell_callback);
+    print_prompt();
+}
diff --git a/src/kernel/utils.c b/src/kernel/utils.c
new file mode 100644 (file)
index 0000000..3abcfdb
--- /dev/null
@@ -0,0 +1,81 @@
+#include "utils.h"
+
+size_t strlen(const char* str) {
+    size_t len = 0;
+    while (str[len])
+        len++;
+    return len;
+}
+
+int strcmp(const char* s1, const char* s2) {
+    while (*s1 && (*s1 == *s2)) {
+        s1++;
+        s2++;
+    }
+    return *(const unsigned char*)s1 - *(const unsigned char*)s2;
+}
+
+int strncmp(const char* s1, const char* s2, size_t n) {
+    while (n && *s1 && (*s1 == *s2)) {
+        s1++;
+        s2++;
+        n--;
+    }
+    if (n == 0) return 0;
+    return *(const unsigned char*)s1 - *(const unsigned char*)s2;
+}
+
+void* memset(void* ptr, int value, size_t num) {
+    unsigned char* p = ptr;
+    while (num--)
+        *p++ = (unsigned char)value;
+    return ptr;
+}
+
+void* memcpy(void* dst, const void* src, size_t n) {
+    char* d = dst;
+    const char* s = src;
+    while (n--)
+        *d++ = *s++;
+    return dst;
+}
+
+void reverse(char* str, int length) {
+    int start = 0;
+    int end = length - 1;
+    while (start < end) {
+        char temp = str[start];
+        str[start] = str[end];
+        str[end] = temp;
+        start++;
+        end--;
+    }
+}
+
+void itoa(int num, char* str, int base) {
+    int i = 0;
+    int isNegative = 0;
+  
+    if (num == 0) {
+        str[i++] = '0';
+        str[i] = '\0';
+        return;
+    }
+  
+    if (num < 0 && base == 10) {
+        isNegative = 1;
+        num = -num;
+    }
+  
+    while (num != 0) {
+        int rem = num % base;
+        str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
+        num = num / base;
+    }
+  
+    if (isNegative)
+        str[i++] = '-';
+  
+    str[i] = '\0';
+    reverse(str, i);
+}