Proper kernel
This commit is contained in:
242
commands.c
Normal file
242
commands.c
Normal file
@@ -0,0 +1,242 @@
|
||||
#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");
|
||||
}
|
||||
Reference in New Issue
Block a user