Files
Operator-system/kernel.c

145 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* kernel.c Kernel entry point and interactive shell loop.
*
* kmain() is called by the loader (main.c) after the ELF kernel has been
* mapped into memory. It initialises subsystems (IDT, memory, tasks),
* prints a welcome banner, and enters an interactive read-eval-print
* loop that dispatches typed commands via commands.c.
*
* While waiting for keyboard input, the shell yields to the cooperative
* scheduler so that background tasks can make progress.
*/
#include "kernel_types.h"
#include "boot_info.h"
#include "commands.h"
#include "idt.h"
#include "memory.h"
#include "task.h"
/* Null-safe print helper used throughout the kernel. */
#define SAFE_PRINT(Boot, ...) \
do { \
if ((Boot) != NULL && (Boot)->print != NULL) { \
(Boot)->print(__VA_ARGS__); \
} \
} while (0)
/* Simple text attribute helper (modelled after UEFI TEXT_ATTR). */
#define TEXT_ATTR(fg, bg) (UINTN)(((fg) & 0x0F) | (((bg) & 0x0F) << 4))
/* Basic colour constants (compatible with UEFI's palette). */
#define COLOR_BLACK 0x0
#define COLOR_LIGHTGREEN 0xA
/* ================================================================
* Kernel entry point
* ================================================================ */
void kmain(BootInfo *Boot)
{
KeyEvent Key;
KSTATUS Status;
UINTN read_errors = 0;
if (Boot == NULL) {
return;
}
if (Boot->clear_screen != NULL) {
Status = Boot->clear_screen();
if (Status != 0) {
SAFE_PRINT(Boot, L"clear_screen failed (status=%ld)\n\r",
(UINT64)Status);
}
}
if (Boot->set_attribute != NULL) {
Status = Boot->set_attribute(TEXT_ATTR(COLOR_LIGHTGREEN, COLOR_BLACK));
if (Status != 0) {
SAFE_PRINT(Boot, L"set_attribute failed (status=%ld)\n\r",
(UINT64)Status);
}
}
/* ---- Subsystem initialisation ---- */
idt_init(Boot);
memory_init(Boot);
task_init(Boot);
/* ---- Welcome banner ---- */
SAFE_PRINT(Boot, L" Welcome to Simple 64-bit Operating System!\n\r");
SAFE_PRINT(Boot, L"================================================\n\r");
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"System Information:\n\r");
if (Boot->firmware_vendor != NULL) {
SAFE_PRINT(Boot, L" Firmware Vendor: %s\n\r", Boot->firmware_vendor);
SAFE_PRINT(Boot, L" Firmware Revision: %d.%d\n\r",
Boot->firmware_major, Boot->firmware_minor);
} else {
SAFE_PRINT(Boot, L" Firmware information: Unavailable\n\r");
}
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"Available Services:\n\r");
SAFE_PRINT(Boot, L" - Console Input/Output: %s\n\r",
(Boot->read_key != NULL && Boot->print != NULL) ? L"Active" : L"Unavailable");
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"Type 'help' for a list of commands.\n\r\n\r");
/* ---- Interactive shell loop ---- */
CHAR16 line[128];
UINTN len = 0;
SAFE_PRINT(Boot, L"-> ");
while (TRUE) {
/* Try non-blocking read first; yield to other tasks while idle */
if (Boot->try_read_key != NULL) {
Status = Boot->try_read_key(&Key);
if (Status != 0) {
task_yield();
continue;
}
} else if (Boot->read_key != NULL) {
Status = Boot->read_key(&Key);
} else {
SAFE_PRINT(Boot, L"Console input unavailable.\n\r");
break;
}
if (Status != 0) {
read_errors++;
if (read_errors == 1 || (read_errors % 64) == 0) {
SAFE_PRINT(Boot, L"read_key failed (status=%ld)\n\r",
(UINT64)Status);
}
continue;
}
read_errors = 0;
if (Key.unicode_char == L'\r' || Key.unicode_char == L'\n') {
/* Enter pressed: execute the buffered command */
line[len] = L'\0';
SAFE_PRINT(Boot, L"\n\r");
execute_command(Boot, line);
/* Reset for next command */
len = 0;
SAFE_PRINT(Boot, L"-> ");
} else if (Key.scan_code == 0x08 || Key.unicode_char == L'\b' || Key.unicode_char == 0x7F) {
/* Backspace */
if (len > 0) {
len--;
SAFE_PRINT(Boot, L"\b \b");
}
} else if (Key.unicode_char >= 32 && Key.unicode_char < 127) {
/* Printable ASCII */
if (len < (sizeof(line) / sizeof(line[0]) - 1)) {
line[len++] = Key.unicode_char;
SAFE_PRINT(Boot, L"%c", Key.unicode_char);
}
}
}
}