243 lines
6.7 KiB
C
243 lines
6.7 KiB
C
#include <efi.h>
|
|
#include "commands.h"
|
|
#include "string_utils.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);
|
|
|
|
// 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
|
|
},
|
|
{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" - 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");
|
|
}
|
|
|
|
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");
|
|
}
|