Better docs and structure

This commit is contained in:
2026-02-26 21:33:16 +00:00
parent d449150169
commit 13a281fa4f
18 changed files with 892 additions and 387 deletions

View File

@@ -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");
}