Files
Operator-system/kernel.c

144 lines
4.9 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 UEFI 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 <efi.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)
/* ================================================================
* Kernel entry point
* ================================================================ */
void kmain(BootInfo *Boot)
{
EFI_INPUT_KEY Key;
EFI_STATUS Status;
UINTN read_errors = 0;
if (Boot == NULL) {
return;
}
if (Boot->clear_screen != NULL) {
Status = Boot->clear_screen();
if (EFI_ERROR(Status)) {
SAFE_PRINT(Boot, L"clear_screen failed: %r\n\r", Status);
}
}
if (Boot->set_attribute != NULL) {
Status = Boot->set_attribute(EFI_TEXT_ATTR(EFI_LIGHTGREEN, EFI_BLACK));
if (EFI_ERROR(Status)) {
SAFE_PRINT(Boot, L"set_attribute failed: %r\n\r", Status);
}
}
/* ---- Subsystem initialisation ---- */
idt_init(Boot);
memory_init(Boot);
task_init(Boot);
/* ---- Welcome banner ---- */
SAFE_PRINT(Boot, L" Welcome to Simple UEFI 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->SystemTable != NULL) {
SAFE_PRINT(Boot, L" UEFI Firmware Vendor: %s\n\r",
Boot->SystemTable->FirmwareVendor);
SAFE_PRINT(Boot, L" UEFI Firmware Revision: %d.%d\n\r",
Boot->SystemTable->FirmwareRevision >> 16,
Boot->SystemTable->FirmwareRevision & 0xFFFF);
} else {
SAFE_PRINT(Boot, L" UEFI System Table: 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" - Runtime Services: %s\n\r",
(Boot->SystemTable != NULL &&
Boot->SystemTable->RuntimeServices != NULL) ? L"Active" : L"Unavailable");
SAFE_PRINT(Boot, L" - Boot Services: %s\n\r",
(Boot->SystemTable != NULL &&
Boot->SystemTable->BootServices != 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 == EFI_NOT_READY) {
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 (EFI_ERROR(Status)) {
read_errors++;
if (read_errors == 1 || (read_errors % 64) == 0) {
SAFE_PRINT(Boot, L"read_key failed: %r\n\r", Status);
}
continue;
}
read_errors = 0;
if (Key.UnicodeChar == L'\r' || Key.UnicodeChar == 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.ScanCode == 0x08 || Key.UnicodeChar == L'\b' || Key.UnicodeChar == 0x7F) {
/* Backspace */
if (len > 0) {
len--;
SAFE_PRINT(Boot, L"\b \b");
}
} else if (Key.UnicodeChar >= 32 && Key.UnicodeChar < 127) {
/* Printable ASCII */
if (len < (sizeof(line) / sizeof(line[0]) - 1)) {
line[len++] = Key.UnicodeChar;
SAFE_PRINT(Boot, L"%c", Key.UnicodeChar);
}
}
}
}