#include #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 \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 \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 \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"); }