Added privilidges
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
User interaction with the kernel is mediated by the **Starling Terminal** and a command registry implemented in `kernel.c` and `commands.c`.
|
||||
|
||||
- The **Starling Terminal** is a task that runs a read–eval–print loop, reading keystrokes via `BootInfo` services and dispatching commands.
|
||||
- The **command subsystem** maintains a table of commands, each with a name, description, usage string, and handler function.
|
||||
- The **command subsystem** maintains a table of commands, each with a name, description, usage string, minimum privilege level, and handler function.
|
||||
- Each command typically runs in its own task so that long-running work does not block the terminal.
|
||||
|
||||
---
|
||||
@@ -23,15 +23,18 @@ static void starling_terminal_task(void *arg)
|
||||
CHAR16 line[128];
|
||||
UINTN len = 0;
|
||||
UINTN depth = 0;
|
||||
TaskPrivilege shell_priv;
|
||||
|
||||
if (ctx == NULL || ctx->Boot == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boot = ctx->Boot;
|
||||
depth = ctx->depth;
|
||||
Boot = ctx->Boot;
|
||||
depth = ctx->depth;
|
||||
shell_priv = ctx->shell_priv;
|
||||
|
||||
SAFE_PRINT(Boot, L"\n\r[Starling Terminal depth %d] ready.\n\r\n\r", depth);
|
||||
SAFE_PRINT(Boot, L"\n\r[Starling Terminal depth %d, priv %d] ready.\n\r\n\r",
|
||||
depth, (INT32)shell_priv);
|
||||
SAFE_PRINT(Boot, L"starling> ");
|
||||
|
||||
while (TRUE) {
|
||||
@@ -66,7 +69,7 @@ static void starling_terminal_task(void *arg)
|
||||
trim_spaces_inplace(line);
|
||||
...
|
||||
} else {
|
||||
Task *cmd_task = execute_command(Boot, line);
|
||||
Task *cmd_task = execute_command(Boot, line, shell_priv);
|
||||
|
||||
/* If a command task was spawned, wait for it to finish. */
|
||||
if (cmd_task != NULL) {
|
||||
@@ -117,16 +120,21 @@ ctx = (StarlingContext *)kmalloc(sizeof(StarlingContext));
|
||||
if (ctx == NULL) {
|
||||
SAFE_PRINT(Boot, L"Failed to allocate Starling Terminal context; starting inline.\n\r");
|
||||
StarlingContext inline_ctx;
|
||||
inline_ctx.Boot = Boot;
|
||||
inline_ctx.depth = 0;
|
||||
inline_ctx.Boot = Boot;
|
||||
inline_ctx.depth = 0;
|
||||
inline_ctx.shell_priv = TASK_PRIV_USER;
|
||||
starling_terminal_task(&inline_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->Boot = Boot;
|
||||
ctx->depth = 0;
|
||||
ctx->Boot = Boot;
|
||||
ctx->depth = 0;
|
||||
ctx->shell_priv = TASK_PRIV_USER;
|
||||
|
||||
terminal_task = task_create(L"starling-term", starling_terminal_task, ctx);
|
||||
terminal_task = task_create_with_priv(L"starling-term",
|
||||
starling_terminal_task,
|
||||
ctx,
|
||||
TASK_PRIV_USER);
|
||||
if (terminal_task == NULL) {
|
||||
SAFE_PRINT(Boot, L"Failed to start Starling Terminal task; falling back to kernel loop.\n\r");
|
||||
...
|
||||
@@ -153,69 +161,88 @@ This ensures that:
|
||||
|
||||
The command registry is defined in `commands.c` as a static array:
|
||||
|
||||
```73:144:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
```73:164:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
static Command commands[] = {
|
||||
{
|
||||
L"shutdown",
|
||||
L"Shutdown the system",
|
||||
L"Usage: shutdown\n\r Initiates a system shutdown using UEFI runtime services.",
|
||||
TASK_PRIV_KERNEL,
|
||||
cmd_shutdown
|
||||
},
|
||||
{
|
||||
L"help",
|
||||
L"Display available commands",
|
||||
L"Usage: help\n\r Lists all available commands with brief descriptions.",
|
||||
TASK_PRIV_USER,
|
||||
cmd_help
|
||||
},
|
||||
{
|
||||
L"man",
|
||||
L"Display manual page for a command",
|
||||
L"Usage: man <command>\n\r Shows detailed help for the specified command.",
|
||||
TASK_PRIV_USER,
|
||||
cmd_man
|
||||
},
|
||||
{
|
||||
L"clear",
|
||||
L"Clear the screen",
|
||||
L"Usage: clear\n\r Clears the console screen.",
|
||||
TASK_PRIV_USER,
|
||||
cmd_clear
|
||||
},
|
||||
{
|
||||
L"about",
|
||||
L"Display system information",
|
||||
L"Usage: about\n\r Shows information about this operating system.",
|
||||
TASK_PRIV_USER,
|
||||
cmd_about
|
||||
},
|
||||
{
|
||||
L"mem",
|
||||
L"Display memory statistics",
|
||||
L"Usage: mem\n\r Shows physical memory, heap, and paging information.",
|
||||
TASK_PRIV_KERNEL,
|
||||
cmd_mem
|
||||
},
|
||||
{
|
||||
L"ps",
|
||||
L"List running tasks",
|
||||
L"Usage: ps\n\r Displays all active tasks with PID, state, and name.",
|
||||
TASK_PRIV_DRIVER,
|
||||
cmd_ps
|
||||
},
|
||||
{
|
||||
L"spawn",
|
||||
L"Spawn a demo background task",
|
||||
L"Usage: spawn [name]\n\r Creates a cooperative demo task.\n\r Optional argument sets the task name.",
|
||||
TASK_PRIV_DRIVER,
|
||||
cmd_spawn
|
||||
},
|
||||
{
|
||||
L"memtest",
|
||||
L"Test memory allocation and deallocation",
|
||||
...
|
||||
TASK_PRIV_KERNEL,
|
||||
cmd_memtest
|
||||
},
|
||||
{
|
||||
L"tasktest",
|
||||
L"Test task scheduler with multiple tasks",
|
||||
...
|
||||
TASK_PRIV_DRIVER,
|
||||
cmd_tasktest
|
||||
},
|
||||
{NULL, NULL, NULL, NULL} /* sentinel */
|
||||
{
|
||||
L"kusr",
|
||||
L"Run a command with kernel privilege",
|
||||
L"Usage: kusr <command> [args...]\n\r"
|
||||
L" Temporarily elevates the current task to kernel privilege,\n\r"
|
||||
L" executes the given command, then restores the original level.",
|
||||
TASK_PRIV_USER,
|
||||
cmd_kusr
|
||||
},
|
||||
{NULL, NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
```
|
||||
|
||||
@@ -224,6 +251,7 @@ Each `Command` entry includes:
|
||||
- `name` – the token typed at the prompt.
|
||||
- `description` – a short summary used by `help`.
|
||||
- `usage` – a longer description and usage details for `man`.
|
||||
- `min_priv` – the minimum `TaskPrivilege` required to run the command (see `task.h`).
|
||||
- `handler` – a function of type:
|
||||
|
||||
```14:19:/home/lochlan/Documents/Coding/c/os/commands.h
|
||||
@@ -246,7 +274,7 @@ To add a new command, follow the guide in the file header:
|
||||
The central function that processes a line of user input is `execute_command`:
|
||||
|
||||
```493:557:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
Task *execute_command(BootInfo *Boot, CHAR16 *Input)
|
||||
Task *execute_command(BootInfo *Boot, CHAR16 *Input, TaskPrivilege caller_priv)
|
||||
{
|
||||
CHAR16 *cmd_start = NULL;
|
||||
CHAR16 *args_start = NULL;
|
||||
@@ -299,7 +327,10 @@ Task *execute_command(BootInfo *Boot, CHAR16 *Input)
|
||||
ctx->handler = commands[i].handler;
|
||||
wstrcpy16_local(ctx->args, args_start, sizeof(ctx->args) / sizeof(ctx->args[0]));
|
||||
|
||||
t = task_create(commands[i].name, command_task_entry, ctx);
|
||||
t = task_create_with_priv(commands[i].name,
|
||||
command_task_entry,
|
||||
ctx,
|
||||
caller_priv);
|
||||
if (t == NULL) {
|
||||
SAFE_PRINT(Boot, L"Failed to create task for command '%s'; running in core thread.\n\r",
|
||||
commands[i].name);
|
||||
@@ -336,10 +367,11 @@ Pipeline stages:
|
||||
- `Boot` pointer.
|
||||
- Handler function.
|
||||
- A bounded copy of the argument string.
|
||||
- A new task is created via `task_create` with:
|
||||
- A new task is created via `task_create_with_priv` with:
|
||||
- Task name = command name.
|
||||
- Entry = `command_task_entry`.
|
||||
- Argument = pointer to the context.
|
||||
- Privilege = `caller_priv` (inherited from the calling shell).
|
||||
- If task creation fails, the command handler is run synchronously in the current thread as a fallback.
|
||||
|
||||
The terminal then optionally `task_wait`s on the returned `Task *`, serialising command execution from the user's perspective while still letting the scheduler run other tasks (e.g., background demos).
|
||||
@@ -396,19 +428,21 @@ This design gives each command:
|
||||
Some notable built-in handlers:
|
||||
|
||||
- **System control**:
|
||||
- `shutdown` → `cmd_shutdown` calls `Boot->shutdown` via `request_shutdown` to power off the machine.
|
||||
- `clear` → `cmd_clear` uses `Boot->clear_screen` to wipe the console.
|
||||
- `shutdown` (KERNEL) → `cmd_shutdown` calls `Boot->shutdown` via `request_shutdown` to power off the machine. `request_shutdown` enforces kernel privilege.
|
||||
- `clear` (USER) → `cmd_clear` uses `Boot->clear_screen` to wipe the console.
|
||||
- **Information and help**:
|
||||
- `help` → `cmd_help` calls `show_help` to print a formatted table of available commands.
|
||||
- `man` → `cmd_man` prints the `usage` field for a specific command.
|
||||
- `about` → `cmd_about` prints OS information and feature list.
|
||||
- `help` (USER) → `cmd_help` calls `show_help` to print a formatted table of available commands.
|
||||
- `man` (USER) → `cmd_man` prints the `usage` field for a specific command.
|
||||
- `about` (USER) → `cmd_about` prints OS information and feature list.
|
||||
- **Diagnostics**:
|
||||
- `mem` → `cmd_mem` calls `memory_print_stats` to show PMM and heap state.
|
||||
- `ps` → `cmd_ps` calls `task_print_list` to show current tasks.
|
||||
- `memtest` → `cmd_memtest` exercises heap and PMM allocations.
|
||||
- `tasktest` → `cmd_tasktest` spawns multiple worker tasks to demonstrate cooperative scheduling.
|
||||
- `mem` (KERNEL) → `cmd_mem` calls `memory_print_stats` to show PMM and heap state. The callee enforces kernel privilege.
|
||||
- `ps` (DRIVER) → `cmd_ps` calls `task_print_list` to show current tasks. The callee enforces driver privilege.
|
||||
- `memtest` (KERNEL) → `cmd_memtest` exercises heap and PMM allocations. The handler enforces kernel privilege.
|
||||
- `tasktest` (DRIVER) → `cmd_tasktest` spawns multiple worker tasks to demonstrate cooperative scheduling.
|
||||
- **Tasking demo**:
|
||||
- `spawn` → `cmd_spawn` creates a demonstration task using `demo_task_fn`, which yields in a loop and reports progress.
|
||||
- `spawn` (DRIVER) → `cmd_spawn` creates a demonstration task using `demo_task_fn`, which yields in a loop and reports progress.
|
||||
- **Privilege escalation**:
|
||||
- `kusr` (USER) → `cmd_kusr` temporarily elevates the calling task to `TASK_PRIV_KERNEL`, dispatches the given sub-command, then restores the original privilege level.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -441,11 +475,12 @@ To add a new command `foo`:
|
||||
|
||||
1. **Declare the handler** near the top of `commands.c`:
|
||||
|
||||
```32:41:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
```32:42:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
static void cmd_shutdown(BootInfo *Boot, CHAR16 *Args);
|
||||
static void cmd_help(BootInfo *Boot, CHAR16 *Args);
|
||||
...
|
||||
static void cmd_tasktest(BootInfo *Boot, CHAR16 *Args);
|
||||
static void cmd_kusr(BootInfo *Boot, CHAR16 *Args);
|
||||
/* Add: */
|
||||
static void cmd_foo(BootInfo *Boot, CHAR16 *Args);
|
||||
```
|
||||
@@ -465,13 +500,14 @@ Use this as a template for `cmd_foo`, replacing the body with your logic and usi
|
||||
|
||||
3. **Register the command** in `commands[]` before the sentinel:
|
||||
|
||||
```140:143:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
```140:164:/home/lochlan/Documents/Coding/c/os/commands.c
|
||||
{
|
||||
L"tasktest",
|
||||
L"kusr",
|
||||
...
|
||||
cmd_tasktest
|
||||
TASK_PRIV_USER,
|
||||
cmd_kusr
|
||||
},
|
||||
{NULL, NULL, NULL, NULL} /* sentinel */
|
||||
{NULL, NULL, NULL, 0, NULL} /* sentinel */
|
||||
```
|
||||
|
||||
Insert a new block above the sentinel:
|
||||
@@ -481,6 +517,7 @@ Insert a new block above the sentinel:
|
||||
L"foo",
|
||||
L"One-line description",
|
||||
L"Usage: foo [args]\n\r Detailed explanation...",
|
||||
TASK_PRIV_USER, /* minimum privilege required */
|
||||
cmd_foo
|
||||
},
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user