Better docs and structure
This commit is contained in:
75
commands.c
75
commands.c
@@ -1,9 +1,23 @@
|
||||
/*
|
||||
* commands.c – Shell command registry and handler implementations.
|
||||
*
|
||||
* Each command is a { name, description, usage, handler } entry in the
|
||||
* static `commands[]` table. execute_command() splits user input into
|
||||
* command + arguments and dispatches to the matching handler.
|
||||
*
|
||||
* To add a new command:
|
||||
* 1. Write a static handler cmd_foo(BootInfo *Boot, CHAR16 *Args)
|
||||
* 2. Add a forward declaration above the table
|
||||
* 3. Append an entry to commands[] (before the sentinel)
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include "commands.h"
|
||||
#include "string_utils.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) { \
|
||||
@@ -11,7 +25,10 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Forward declarations
|
||||
/* ================================================================
|
||||
* 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);
|
||||
@@ -23,7 +40,10 @@ static void cmd_spawn(BootInfo *Boot, CHAR16 *Args);
|
||||
static void cmd_memtest(BootInfo *Boot, CHAR16 *Args);
|
||||
static void cmd_tasktest(BootInfo *Boot, CHAR16 *Args);
|
||||
|
||||
// Command registry
|
||||
/* ================================================================
|
||||
* Command registry
|
||||
* ================================================================ */
|
||||
|
||||
static Command commands[] = {
|
||||
{
|
||||
L"shutdown",
|
||||
@@ -85,9 +105,17 @@ static Command commands[] = {
|
||||
L"Usage: tasktest\n\r Spawns several concurrent tasks that run cooperatively\n\r and report their progress, demonstrating context switching.",
|
||||
cmd_tasktest
|
||||
},
|
||||
{NULL, NULL, NULL, NULL} // Sentinel
|
||||
{NULL, NULL, NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
/* ================================================================
|
||||
* System control
|
||||
* ================================================================ */
|
||||
|
||||
/*
|
||||
* Try Boot->shutdown first, then fall back to RuntimeServices, then
|
||||
* print an error if neither is available.
|
||||
*/
|
||||
static void request_shutdown(BootInfo *Boot)
|
||||
{
|
||||
if (Boot == NULL) {
|
||||
@@ -110,16 +138,20 @@ static void request_shutdown(BootInfo *Boot)
|
||||
SAFE_PRINT(Boot, L"Shutdown service unavailable.\n\r");
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Built-in command handlers
|
||||
* ================================================================ */
|
||||
|
||||
static void cmd_shutdown(BootInfo *Boot, CHAR16 *Args)
|
||||
{
|
||||
(void)Args; // Unused
|
||||
(void)Args;
|
||||
SAFE_PRINT(Boot, L"Shutting down...\n\r");
|
||||
request_shutdown(Boot);
|
||||
}
|
||||
|
||||
static void cmd_help(BootInfo *Boot, CHAR16 *Args)
|
||||
{
|
||||
(void)Args; // Unused
|
||||
(void)Args;
|
||||
show_help(Boot);
|
||||
}
|
||||
|
||||
@@ -154,7 +186,7 @@ static void cmd_man(BootInfo *Boot, CHAR16 *Args)
|
||||
static void cmd_clear(BootInfo *Boot, CHAR16 *Args)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
(void)Args; // Unused
|
||||
(void)Args;
|
||||
|
||||
if (Boot != NULL && Boot->clear_screen != NULL) {
|
||||
Status = Boot->clear_screen();
|
||||
@@ -168,8 +200,8 @@ static void cmd_clear(BootInfo *Boot, CHAR16 *Args)
|
||||
|
||||
static void cmd_about(BootInfo *Boot, CHAR16 *Args)
|
||||
{
|
||||
(void)Args; // Unused
|
||||
|
||||
(void)Args;
|
||||
|
||||
SAFE_PRINT(Boot, L"\n\r");
|
||||
SAFE_PRINT(Boot, L"================================================\n\r");
|
||||
SAFE_PRINT(Boot, L" Simple UEFI Operating System\n\r");
|
||||
@@ -378,6 +410,11 @@ static void cmd_tasktest(BootInfo *Boot, CHAR16 *Args)
|
||||
SAFE_PRINT(Boot, L"Task scheduler test completed.\n\r\n\r");
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Public API
|
||||
* ================================================================ */
|
||||
|
||||
/* Print a formatted table of all registered commands. */
|
||||
void show_help(BootInfo *Boot)
|
||||
{
|
||||
UINTN i = 0;
|
||||
@@ -389,7 +426,7 @@ void show_help(BootInfo *Boot)
|
||||
SAFE_PRINT(Boot, L"Available commands:\n\r");
|
||||
SAFE_PRINT(Boot, L"\n\r");
|
||||
|
||||
// Find longest command name for formatting
|
||||
/* Find the longest command name for column alignment */
|
||||
for (i = 0; commands[i].name != NULL; i++) {
|
||||
name_len = 0;
|
||||
while (commands[i].name[name_len] != L'\0') {
|
||||
@@ -403,7 +440,7 @@ void show_help(BootInfo *Boot)
|
||||
for (i = 0; commands[i].name != NULL; i++) {
|
||||
SAFE_PRINT(Boot, L" %s", commands[i].name);
|
||||
|
||||
// Add padding
|
||||
/* Pad to align descriptions */
|
||||
name_len = 0;
|
||||
while (commands[i].name[name_len] != L'\0') {
|
||||
name_len++;
|
||||
@@ -420,6 +457,10 @@ void show_help(BootInfo *Boot)
|
||||
SAFE_PRINT(Boot, L"\n\r");
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a line of user input into command + arguments and dispatch
|
||||
* to the matching handler. Unknown commands print an error.
|
||||
*/
|
||||
void execute_command(BootInfo *Boot, CHAR16 *Input)
|
||||
{
|
||||
CHAR16 *cmd_start = NULL;
|
||||
@@ -436,27 +477,27 @@ void execute_command(BootInfo *Boot, CHAR16 *Input)
|
||||
return;
|
||||
}
|
||||
|
||||
// Split command and arguments
|
||||
/* Split input into command and argument strings */
|
||||
cmd_start = Input;
|
||||
args_start = Input;
|
||||
|
||||
// Find first space
|
||||
|
||||
/* Advance past the command keyword */
|
||||
while (*args_start != L'\0' && !is_space16(*args_start)) {
|
||||
args_start++;
|
||||
}
|
||||
|
||||
// If we found a space, null-terminate command and advance to args
|
||||
/* NUL-terminate the command and skip leading whitespace in args */
|
||||
if (*args_start != L'\0') {
|
||||
*args_start = L'\0';
|
||||
args_start++;
|
||||
|
||||
// Skip leading spaces in args
|
||||
/* skip leading whitespace in args */
|
||||
while (*args_start != L'\0' && is_space16(*args_start)) {
|
||||
args_start++;
|
||||
}
|
||||
}
|
||||
|
||||
// Search for command
|
||||
/* Look up and dispatch the command */
|
||||
for (i = 0; commands[i].name != NULL; i++) {
|
||||
if (ascii_streq_ci(cmd_start, commands[i].name)) {
|
||||
commands[i].handler(Boot, args_start);
|
||||
@@ -464,7 +505,7 @@ void execute_command(BootInfo *Boot, CHAR16 *Input)
|
||||
}
|
||||
}
|
||||
|
||||
// Command not found
|
||||
/* 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