--- /dev/null
+#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
--- /dev/null
+#ifndef SHELL_H
+#define SHELL_H
+
+void shell_init(void);
+
+#endif
--- /dev/null
+#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
--- /dev/null
+#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;
+}
#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)
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.
}
}
--- /dev/null
+#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();
+}
--- /dev/null
+#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);
+}