]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: implement kconsole — kernel emergency console (like HelenOS kconsole)
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 06:01:02 +0000 (03:01 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 06:01:02 +0000 (03:01 -0300)
When VFS mount or init fails, AdrOS now enters a minimal kernel-mode
emergency console instead of the full shell. This is similar to
HelenOS's kconsole — it runs entirely in kernel mode and provides
basic diagnostic commands.

Design:
- kconsole_enter() runs a blocking read loop using kgetc()/kprintf()
- Commands: help, dmesg, reboot, halt
- Activated from kernel_main() when init_start() returns < 0
- Fully architecture-independent (uses only generic console API)

The normal shell remains available for userspace-initiated sessions.

Passes: make, cppcheck, QEMU smoke test.

include/kconsole.h [new file with mode: 0644]
src/kernel/kconsole.c [new file with mode: 0644]
src/kernel/main.c

diff --git a/include/kconsole.h b/include/kconsole.h
new file mode 100644 (file)
index 0000000..fcf8d48
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef KCONSOLE_H
+#define KCONSOLE_H
+
+// Enter the kernel emergency console (kernel-mode, like HelenOS kconsole).
+// Called when VFS mount or init fails. Runs in a loop until reboot.
+void kconsole_enter(void);
+
+#endif
diff --git a/src/kernel/kconsole.c b/src/kernel/kconsole.c
new file mode 100644 (file)
index 0000000..53244b1
--- /dev/null
@@ -0,0 +1,79 @@
+#include "kconsole.h"
+#include "console.h"
+#include "utils.h"
+#include "hal/system.h"
+#include "hal/cpu.h"
+
+#define KCMD_MAX 128
+
+static void kconsole_help(void) {
+    kprintf("kconsole commands:\n");
+    kprintf("  help   - Show this list\n");
+    kprintf("  dmesg  - Show kernel log buffer\n");
+    kprintf("  reboot - Restart system\n");
+    kprintf("  halt   - Halt the CPU\n");
+}
+
+static void kconsole_exec(const char* cmd) {
+    if (strcmp(cmd, "help") == 0) {
+        kconsole_help();
+    }
+    else if (strcmp(cmd, "dmesg") == 0) {
+        char buf[4096];
+        size_t n = klog_read(buf, sizeof(buf));
+        if (n > 0) {
+            console_write(buf);
+        } else {
+            kprintf("(empty)\n");
+        }
+    }
+    else if (strcmp(cmd, "reboot") == 0) {
+        hal_system_reboot();
+    }
+    else if (strcmp(cmd, "halt") == 0) {
+        kprintf("System halted.\n");
+        hal_cpu_disable_interrupts();
+        for (;;) hal_cpu_idle();
+    }
+    else if (cmd[0] != '\0') {
+        kprintf("unknown command: %s\n", cmd);
+    }
+}
+
+void kconsole_enter(void) {
+    kprintf("\n*** AdrOS Kernel Console (kconsole) ***\n");
+    kprintf("Type 'help' for available commands.\n");
+
+    char line[KCMD_MAX];
+    int pos = 0;
+
+    for (;;) {
+        kprintf("kconsole> ");
+
+        pos = 0;
+        while (pos < KCMD_MAX - 1) {
+            int ch = kgetc();
+            if (ch < 0) continue;
+
+            if (ch == '\n' || ch == '\r') {
+                console_write("\n");
+                break;
+            }
+
+            if (ch == '\b' || ch == 127) {
+                if (pos > 0) {
+                    pos--;
+                    console_write("\b \b");
+                }
+                continue;
+            }
+
+            line[pos++] = (char)ch;
+            char echo[2] = { (char)ch, 0 };
+            console_write(echo);
+        }
+        line[pos] = '\0';
+
+        kconsole_exec(line);
+    }
+}
index cdbf1055b579845a66586d38ed18ec318588f70c..609ae557819822f6208e7243c521ff261671dffa 100644 (file)
@@ -8,6 +8,7 @@
 #include "process.h"
 #include "keyboard.h"
 #include "shell.h"
+#include "kconsole.h"
 #include "heap.h"
 #include "timer.h"
 #include "initrd.h"
@@ -62,8 +63,8 @@ void kernel_main(const struct boot_info* bi) {
     int init_ret = init_start(bi);
     
     if (init_ret < 0) {
-        // Start Shell as the main interaction loop
-        shell_init();
+        // VFS/init failed — enter kernel emergency console
+        kconsole_enter();
     }
     
 done: