Files
Operator-system/README.md
JimmyBinoculars 7ecf26cbd9 Add command task execution and improve command documentation
Introduced a new CommandTaskContext structure to facilitate command execution in separate tasks. Updated the execute_command function to spawn tasks for commands, enhancing concurrency. Improved documentation for the 'memtest' and 'tasktest' commands in README.md to clarify their functionality and usage. Updated the interactive prompt reference to 'starling>'.
2026-02-27 20:14:11 +00:00

330 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Simple UEFI Operating System
A minimal bootable UEFI operating system written in C that demonstrates UEFI boot loading, memory management, interrupt handling, and cooperative multitasking.
## Features
- **UEFI Boot** — boots directly on UEFI firmware via a PE32+ loader
- **ELF64 Kernel Loader** — reads and maps a standalone kernel from the EFI partition
- **Console I/O** — interactive keyboard input and screen output
- **Interrupt Handling** — IDT setup with CPU exception handlers (vectors 031) and hardware IRQ dispatch
- **Memory Management** — bitmap-based physical memory manager (PMM), 4-level x86-64 paging, and a first-fit heap allocator with block coalescing
- **Cooperative Multitasking** — process control blocks, assembly context switching, and a round-robin task scheduler
- **Interactive Shell** — command registry with `help`, `man`, built-in commands, and test utilities
---
## Getting Started
### Requirements
- GCC cross-compiler (or native x86-64 GCC)
- GNU-EFI library and headers
- QEMU with OVMF firmware
- GNU Make
- `xorriso` and `mtools` (for ISO builds only)
### Installation
<details>
<summary><strong>Debian / Ubuntu</strong></summary>
```bash
make install-deps
```
Or manually:
```bash
sudo apt-get install gnu-efi qemu-system-x86 ovmf gcc binutils make xorriso mtools
```
</details>
<details>
<summary><strong>Arch Linux</strong></summary>
```bash
sudo pacman -S gnu-efi qemu-system-x86 edk2-ovmf gcc binutils make xorriso mtools
```
</details>
<details>
<summary><strong>Fedora / RHEL</strong></summary>
```bash
sudo dnf install gnu-efi qemu-system-x86 edk2-ovmf gcc binutils make xorriso mtools
```
</details>
### Building
```bash
make # build both UEFI loader and kernel
```
This produces two binaries:
| Output | Description |
|--------|-------------|
| `build/EFI/BOOT/BOOTX64.EFI` | UEFI loader (PE32+) |
| `build/kernel.elf` | Kernel binary (ELF64) |
### Running
```bash
make run # build and run with QEMU (FAT directory, nographic)
make runiso # build, create ISO, and run with QEMU
```
The loader expects `kernel.elf` at the root of the EFI partition (next to the `EFI/` directory).
| Key / Command | Action |
|---------------|--------|
| `Ctrl+A`, then `X` | Exit QEMU |
| `shutdown` (in shell) | Power off the OS |
### Make Targets
| Target | Description |
|--------|-------------|
| `all` | Build the UEFI loader and kernel (default) |
| `run` | Build and run with QEMU |
| `iso` | Create a bootable ISO image |
| `runiso` | Build, create ISO, and run in QEMU |
| `clean` | Remove all build artifacts |
| `install-deps` | Install required packages (Debian/Ubuntu) |
| `help` | Print target summary |
---
## Usage
### Shell Commands
Once the OS boots, the Starling Terminal displays an interactive prompt (`starling>`). The following built-in commands are available:
| Command | Description |
|---------|-------------|
| `help` | List all available commands |
| `man <command>` | Show detailed help for a command |
| `shutdown` | Shut down the system |
| `clear` | Clear the screen |
| `about` | Display system information |
| `mem` | Display memory statistics (PMM, heap, paging) |
| `ps` | List all active tasks with PID, state, and name |
| `spawn [name]` | Create a demo background task (optional argument sets the task name) |
| `memtest` | Run memory allocation/deallocation and PMM tests |
| `tasktest` | Spawn multiple concurrent tasks to test the scheduler |
In addition, the Starling Terminal itself recognises:
| Command | Description |
|---------|-------------|
| `starling` | Spawn a nested Starling Terminal at increased depth |
| `exit` | Exit the current nested Starling Terminal (not allowed at depth 0) |
### Example Session
```
-> help
-> about
-> mem
-> memtest
-> spawn worker1
-> spawn worker2
-> ps
-> tasktest
-> shutdown
```
### Testing Memory Management
The `memtest` command runs four phases:
1. **Heap allocation** — allocates 8 blocks of increasing size (164096 bytes) via `kmalloc()`
2. **Heap free** — frees all blocks via `kfree()` and verifies coalescing
3. **PMM single page** — allocates and frees a single 4 KB page
4. **PMM multi-page** — allocates and frees 4 contiguous pages
Each phase reports addresses, success/failure, and usage statistics.
### Testing Task Scheduling
The `tasktest` command:
1. Spawns 3 worker tasks (`worker-A`, `worker-B`, `worker-C`)
2. Each worker prints 3 progress steps, yielding between each
3. The shell yields to let workers run in round-robin order
4. Displays the task list after completion
You can also test manually with `spawn` and `ps`:
```
-> spawn myTask
Created task 'myTask' (PID 1)
-> ps
PID STATE SWITCHES NAME
--- ---------- -------- ----
0 RUNNING 5 kernel
1 READY 0 myTask
Active tasks: 2 / 32
```
Background tasks run whenever the shell yields (which happens automatically while waiting for keyboard input).
---
## Architecture
### Boot Flow
```
UEFI Firmware
└─ efi_main() [main.c] PE32+ UEFI application
├─ InitializeLib() GNU-EFI setup
├─ read_file_to_buffer() read kernel.elf from ESP
├─ load_elf_kernel() parse ELF64, map PT_LOAD segments
├─ populate BootInfo wrap UEFI services as fn pointers
└─ kmain(&Boot) [kernel.c] jump to kernel
├─ idt_init() install exception handlers
├─ memory_init() PMM → paging → heap
├─ task_init() scheduler + task 0
└─ Starling Terminal task interactive read-eval-print loop
```
### Memory Management
| Layer | Description |
|-------|-------------|
| **PMM** | Bitmap-based page-frame allocator managing a 16 MB pool (4096 pages). Supports single and contiguous multi-page allocation. |
| **Paging** | Walks and creates 4-level x86-64 page tables (PML4 → PDPT → PD → PT). Supports map, unmap, and virtual-to-physical translation for 4 KB, 2 MB, and 1 GB page sizes. |
| **Heap** | First-fit free-list allocator with block splitting and bidirectional coalescing. 16-byte alignment. Magic-number corruption detection. |
### Task System
| Aspect | Detail |
|--------|--------|
| **PCB** | `Task` struct: PID, state, name, saved RSP, stack base, entry function, scheduling metadata |
| **States** | `FREE``READY``RUNNING``TERMINATED``FREE` |
| **Scheduler** | Round-robin among `READY` tasks via `task_yield()` |
| **Context Switch** | Assembly routine saves/restores callee-saved registers (`rbp`, `rbx`, `r12``r15`) and `RFLAGS`, then swaps RSP |
| **Stack** | 32 KB (8 pages) per task, allocated from PMM, freed on `task_exit()` |
| **Limits** | Up to 32 concurrent tasks; cooperative (voluntary yield) only |
### Command System
Commands are registered in a static array in `commands.c`:
```c
static Command commands[] = {
{ L"name", L"description", L"usage", handler_fn },
...
{ NULL, NULL, NULL, NULL } /* sentinel */
};
```
`execute_command()` splits user input into command + arguments and dispatches to the matching handler. `man` provides detailed help by looking up command metadata.
---
## Project Structure
```
.
├── main.c # UEFI loader — reads kernel.elf, sets up BootInfo
├── kernel.c # Kernel entry point (kmain) and interactive shell
├── kernel.ld # Linker script — kernel loaded at 0x100000
├── boot_info.h # BootInfo struct shared between loader and kernel
├── commands.c # Command registry and all handler implementations
├── commands.h # Command type and dispatch API
├── string_utils.c # CHAR16 string helpers (trim, compare)
├── string_utils.h # String utility declarations
├── idt.c # IDT setup, exception handlers, PIC EOI
├── idt.h # ISRFrame layout and idt_init() declaration
├── isr.S # ISR stub table (vectors 0255) and common handler
├── memory.c # PMM (bitmap), paging (4-level), heap (first-fit)
├── memory.h # Memory subsystem constants, types, and API
├── task.c # PCB pool, round-robin scheduler, yield/exit
├── task.h # Task types (Task, TaskState) and task API
├── context_switch.S # Cooperative context switch (x86-64 assembly)
├── Makefile # Build system
├── README.md # This file
└── build/ # Build output (generated)
├── EFI/BOOT/BOOTX64.EFI
├── kernel.elf
└── image/ # ISO staging area
```
---
## Development
### Adding a New Command
1. Open `commands.c`
2. Add a forward declaration:
```c
static void cmd_foo(BootInfo *Boot, CHAR16 *Args);
```
3. Append an entry to the `commands[]` array (before the `NULL` sentinel):
```c
{ L"foo", L"Short description", L"Usage: foo [args]\n\r Details.", cmd_foo },
```
4. Implement `cmd_foo`
5. Rebuild with `make`
### Building for Real Hardware
1. Build the project: `make`
2. Format a USB drive with GPT and a FAT32 EFI System Partition
3. Mount the ESP
4. Copy `build/EFI/BOOT/BOOTX64.EFI` → `<mount>/EFI/BOOT/BOOTX64.EFI`
5. Copy `build/kernel.elf` → `<mount>/kernel.elf`
6. Boot from the USB in UEFI mode
> **Warning:** Always back up your data before creating bootable media.
---
## Troubleshooting
| Problem | Solution |
|---------|----------|
| **GNU-EFI headers not found** | Install GNU-EFI. Headers are typically at `/usr/include/efi`. Update `EFI_INC` in the Makefile if installed elsewhere. |
| **OVMF firmware not found** | Check `/usr/share/OVMF/`, `/usr/share/qemu/`, or `/usr/share/edk2-ovmf/`. The Makefile auto-detects common paths. |
| **QEMU crashes or won't start** | Ensure `qemu-system-x86_64` and OVMF are installed. Verify with `qemu-system-x86_64 --version`. |
---
## Technical Details
| Property | Value |
|----------|-------|
| Architecture | x86-64 (long mode) |
| Firmware Interface | UEFI 2.x |
| Development Library | GNU-EFI |
| Loader Format | PE32+ (EFI application) |
| Kernel Format | ELF64 (static, loaded at 0x100000) |
| Boot Protocol | UEFI Boot Services |
| Memory Model | Identity-mapped (UEFI), 4-level paging (kernel) |
| Scheduling | Cooperative round-robin multitasking |
## Resources
- [UEFI Specification](https://uefi.org/specifications)
- [GNU-EFI Documentation](https://sourceforge.net/projects/gnu-efi/)
- [OSDev Wiki](https://wiki.osdev.org/)
## License
This is a minimal educational example. Feel free to use and modify as needed.