Files
Operator-system/commands.c

258 lines
7.1 KiB
C

#include <efi.h>
#include "commands.h"
#include "string_utils.h"
#include "memory.h"
#define SAFE_PRINT(Boot, ...) \
do { \
if ((Boot) != NULL && (Boot)->print != NULL) { \
(Boot)->print(__VA_ARGS__); \
} \
} while (0)
// Forward declarations
static void cmd_shutdown(BootInfo *Boot, CHAR16 *Args);
static void cmd_help(BootInfo *Boot, CHAR16 *Args);
static void cmd_man(BootInfo *Boot, CHAR16 *Args);
static void cmd_clear(BootInfo *Boot, CHAR16 *Args);
static void cmd_about(BootInfo *Boot, CHAR16 *Args);
static void cmd_mem(BootInfo *Boot, CHAR16 *Args);
// Command registry
static Command commands[] = {
{
L"shutdown",
L"Shutdown the system",
L"Usage: shutdown\n\r Initiates a system shutdown using UEFI runtime services.",
cmd_shutdown
},
{
L"help",
L"Display available commands",
L"Usage: help\n\r Lists all available commands with brief descriptions.",
cmd_help
},
{
L"man",
L"Display manual page for a command",
L"Usage: man <command>\n\r Shows detailed help for the specified command.",
cmd_man
},
{
L"clear",
L"Clear the screen",
L"Usage: clear\n\r Clears the console screen.",
cmd_clear
},
{
L"about",
L"Display system information",
L"Usage: about\n\r Shows information about this operating system.",
cmd_about
},
{
L"mem",
L"Display memory statistics",
L"Usage: mem\n\r Shows physical memory, heap, and paging information.",
cmd_mem
},
{NULL, NULL, NULL, NULL} // Sentinel
};
static void request_shutdown(BootInfo *Boot)
{
if (Boot == NULL) {
return;
}
if (Boot->shutdown != NULL) {
Boot->shutdown();
return;
}
if (Boot->SystemTable != NULL &&
Boot->SystemTable->RuntimeServices != NULL &&
Boot->SystemTable->RuntimeServices->ResetSystem != NULL) {
Boot->SystemTable->RuntimeServices->ResetSystem(
EfiResetShutdown, EFI_SUCCESS, 0, NULL);
return;
}
SAFE_PRINT(Boot, L"Shutdown service unavailable.\n\r");
}
static void cmd_shutdown(BootInfo *Boot, CHAR16 *Args)
{
(void)Args; // Unused
SAFE_PRINT(Boot, L"Shutting down...\n\r");
request_shutdown(Boot);
}
static void cmd_help(BootInfo *Boot, CHAR16 *Args)
{
(void)Args; // Unused
show_help(Boot);
}
static void cmd_man(BootInfo *Boot, CHAR16 *Args)
{
UINTN i = 0;
if (Args == NULL || Args[0] == L'\0') {
SAFE_PRINT(Boot, L"Usage: man <command>\n\r");
SAFE_PRINT(Boot, L"Try 'help' for a list of available commands.\n\r");
return;
}
trim_spaces_inplace(Args);
for (i = 0; commands[i].name != NULL; i++) {
if (ascii_streq_ci(Args, commands[i].name)) {
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"NAME\n\r");
SAFE_PRINT(Boot, L" %s - %s\n\r\n\r", commands[i].name, commands[i].description);
SAFE_PRINT(Boot, L"DESCRIPTION\n\r");
SAFE_PRINT(Boot, L" %s\n\r", commands[i].usage);
SAFE_PRINT(Boot, L"\n\r");
return;
}
}
SAFE_PRINT(Boot, L"No manual entry for '%s'\n\r", Args);
SAFE_PRINT(Boot, L"Try 'help' for a list of available commands.\n\r");
}
static void cmd_clear(BootInfo *Boot, CHAR16 *Args)
{
EFI_STATUS Status;
(void)Args; // Unused
if (Boot != NULL && Boot->clear_screen != NULL) {
Status = Boot->clear_screen();
if (EFI_ERROR(Status)) {
SAFE_PRINT(Boot, L"Failed to clear screen: %r\n\r", Status);
}
} else {
SAFE_PRINT(Boot, L"Clear screen function unavailable.\n\r");
}
}
static void cmd_about(BootInfo *Boot, CHAR16 *Args)
{
(void)Args; // Unused
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"================================================\n\r");
SAFE_PRINT(Boot, L" Simple UEFI Operating System\n\r");
SAFE_PRINT(Boot, L"================================================\n\r");
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"A minimal bootable UEFI operating system written in C.\n\r");
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"Features:\n\r");
SAFE_PRINT(Boot, L" - UEFI Boot\n\r");
SAFE_PRINT(Boot, L" - Console I/O\n\r");
SAFE_PRINT(Boot, L" - ELF64 Kernel Loader\n\r");
SAFE_PRINT(Boot, L" - Memory Management (PMM + Heap)\n\r");
SAFE_PRINT(Boot, L" - Interactive Command Interface\n\r");
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"Type 'help' for available commands.\n\r");
SAFE_PRINT(Boot, L"\n\r");
}
static void cmd_mem(BootInfo *Boot, CHAR16 *Args)
{
(void)Args;
memory_print_stats(Boot);
}
void show_help(BootInfo *Boot)
{
UINTN i = 0;
UINTN max_len = 0;
UINTN name_len = 0;
UINTN padding = 0;
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"Available commands:\n\r");
SAFE_PRINT(Boot, L"\n\r");
// Find longest command name for formatting
for (i = 0; commands[i].name != NULL; i++) {
name_len = 0;
while (commands[i].name[name_len] != L'\0') {
name_len++;
}
if (name_len > max_len) {
max_len = name_len;
}
}
for (i = 0; commands[i].name != NULL; i++) {
SAFE_PRINT(Boot, L" %s", commands[i].name);
// Add padding
name_len = 0;
while (commands[i].name[name_len] != L'\0') {
name_len++;
}
for (padding = 0; padding < (max_len - name_len + 2); padding++) {
SAFE_PRINT(Boot, L" ");
}
SAFE_PRINT(Boot, L"- %s\n\r", commands[i].description);
}
SAFE_PRINT(Boot, L"\n\r");
SAFE_PRINT(Boot, L"For detailed help on a command, type: man <command>\n\r");
SAFE_PRINT(Boot, L"\n\r");
}
void execute_command(BootInfo *Boot, CHAR16 *Input)
{
CHAR16 *cmd_start = NULL;
CHAR16 *args_start = NULL;
UINTN i = 0;
if (Boot == NULL || Input == NULL) {
return;
}
trim_spaces_inplace(Input);
if (Input[0] == L'\0') {
return;
}
// Split command and arguments
cmd_start = Input;
args_start = Input;
// Find first space
while (*args_start != L'\0' && !is_space16(*args_start)) {
args_start++;
}
// If we found a space, null-terminate command and advance to args
if (*args_start != L'\0') {
*args_start = L'\0';
args_start++;
// Skip leading spaces in args
while (*args_start != L'\0' && is_space16(*args_start)) {
args_start++;
}
}
// Search for command
for (i = 0; commands[i].name != NULL; i++) {
if (ascii_streq_ci(cmd_start, commands[i].name)) {
commands[i].handler(Boot, args_start);
return;
}
}
// Command not found
SAFE_PRINT(Boot, L"Unknown command: %s\n\r", cmd_start);
SAFE_PRINT(Boot, L"Type 'help' for a list of available commands.\n\r");
}