199 lines
5.1 KiB
Markdown
199 lines
5.1 KiB
Markdown
# Simple UEFI Operating System
|
|
|
|
A minimal bootable UEFI operating system written in C that demonstrates basic UEFI functionality.
|
|
|
|
## Features
|
|
|
|
- **UEFI Boot**: Boots directly on UEFI firmware
|
|
- **Console I/O**: Interactive keyboard input and screen output
|
|
- **System Information**: Displays firmware details
|
|
- **Kernel Loader**: Loads an ELF64 kernel from the EFI partition
|
|
- **Simple Commands**: Minimal interactive command interface
|
|
|
|
## Requirements
|
|
|
|
- GCC compiler
|
|
- GNU-EFI library
|
|
- QEMU with OVMF firmware
|
|
- Make
|
|
|
|
## Installation
|
|
|
|
### On Debian/Ubuntu:
|
|
|
|
```bash
|
|
make install-deps
|
|
```
|
|
|
|
Or manually:
|
|
|
|
```bash
|
|
sudo apt-get install gnu-efi qemu-system-x86 ovmf gcc binutils make
|
|
```
|
|
|
|
### On Arch Linux:
|
|
|
|
```bash
|
|
sudo pacman -S gnu-efi qemu-system-x86 edk2-ovmf gcc binutils make
|
|
```
|
|
|
|
### On Fedora/RHEL:
|
|
|
|
```bash
|
|
sudo dnf install gnu-efi qemu-system-x86 edk2-ovmf gcc binutils make
|
|
```
|
|
|
|
## Building
|
|
|
|
Build the UEFI application and kernel:
|
|
|
|
```bash
|
|
make
|
|
```
|
|
|
|
This will create `build/EFI/BOOT/BOOTX64.EFI` and `build/kernel.elf`.
|
|
|
|
## Running
|
|
|
|
Test with QEMU (no graphics mode):
|
|
|
|
```bash
|
|
make run
|
|
```
|
|
|
|
The loader expects `kernel.elf` at the root of the EFI partition (next to the `EFI/` directory).
|
|
|
|
### QEMU Controls:
|
|
- **Exit QEMU**: Press `Ctrl+A`, then `X`
|
|
- **Shutdown OS**: Type `shutdown` in the OS
|
|
|
|
## Commands in the OS
|
|
|
|
Once the OS boots, you can use these commands:
|
|
|
|
- `help` - Display all available commands
|
|
- `man <command>` - Display detailed help for a command
|
|
- `shutdown` - Shutdown the system
|
|
- `clear` - Clear the screen
|
|
- `about` - Display system information
|
|
|
|
Example usage:
|
|
```
|
|
-> help
|
|
-> man shutdown
|
|
-> clear
|
|
-> about
|
|
-> shutdown
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
.
|
|
├── main.c # UEFI loader (reads and loads kernel ELF)
|
|
├── kernel.c # Kernel entry point and main loop
|
|
├── commands.c # Command registry and handlers
|
|
├── commands.h # Command interface definitions
|
|
├── string_utils.c # String utility functions
|
|
├── string_utils.h # String utility declarations
|
|
├── kernel.ld # Kernel linker script
|
|
├── boot_info.h # Shared boot interface
|
|
├── Makefile # Build configuration
|
|
└── README.md # This file
|
|
```
|
|
|
|
## How It Works
|
|
|
|
1. **UEFI Entry Point**: The `efi_main` function is the entry point called by UEFI firmware
|
|
2. **Initialization**: GNU-EFI library is initialized with the system table
|
|
3. **Console Setup**: Output is configured and screen is cleared
|
|
4. **Kernel Load**: The loader reads `kernel.elf` and maps its loadable segments
|
|
5. **Main Loop**: The kernel enters a loop waiting for keyboard input
|
|
6. **Command Processing**: User commands are parsed and dispatched to registered handlers
|
|
7. **Command Execution**: Each command is executed via its handler function
|
|
8. **Shutdown**: UEFI runtime services are used to shutdown the system
|
|
|
|
**Command System Architecture:**
|
|
- Commands are registered in a static array with metadata (name, description, usage, handler)
|
|
- The `execute_command()` function parses input, splits command and arguments, and dispatches to handlers
|
|
- The `man` command provides detailed help by looking up command metadata
|
|
- New commands can be easily added by implementing a handler and registering it
|
|
|
|
## Building for Real Hardware
|
|
|
|
To create a bootable USB drive:
|
|
|
|
1. Build the project: `make`
|
|
2. Format a USB drive with GPT and create an EFI partition (FAT32)
|
|
3. Mount the EFI partition
|
|
4. Copy `build/EFI/BOOT/BOOTX64.EFI` to `/EFI/BOOT/` on the USB drive
|
|
5. Copy `build/kernel.elf` to the root of the EFI partition
|
|
6. Boot from the USB drive in UEFI mode
|
|
|
|
**Warning**: Always backup your data before creating bootable media!
|
|
|
|
## Cleaning
|
|
|
|
Remove build artifacts:
|
|
|
|
```bash
|
|
make clean
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### GNU-EFI headers not found
|
|
|
|
Make sure GNU-EFI is installed. The headers are typically in `/usr/include/efi`.
|
|
|
|
If installed in a different location, update the `EFI_INC` variable in the Makefile.
|
|
|
|
### OVMF firmware not found
|
|
|
|
OVMF files might be in different locations depending on your distribution:
|
|
- `/usr/share/OVMF/`
|
|
- `/usr/share/qemu/`
|
|
- `/usr/share/edk2-ovmf/`
|
|
|
|
Update the paths in the Makefile if needed.
|
|
|
|
### QEMU crashes or fails to start
|
|
|
|
Ensure you have QEMU with x86_64 support and OVMF firmware installed.
|
|
|
|
## Technical Details
|
|
|
|
- **Architecture**: x86_64
|
|
- **Firmware Interface**: UEFI 2.x
|
|
- **Development Library**: GNU-EFI
|
|
- **Executable Format**: PE32+ (Portable Executable for EFI)
|
|
- **Boot Protocol**: UEFI Boot Services
|
|
|
|
## License
|
|
|
|
This is a minimal educational example. Feel free to use and modify as needed.
|
|
|
|
## Further Development
|
|
|
|
The codebase is now modular and easy to extend:
|
|
|
|
**Adding New Commands:**
|
|
1. Open `commands.c`
|
|
2. Create a new handler function: `static void cmd_yourcommand(BootInfo *Boot, CHAR16 *Args)`
|
|
3. Add your command to the `commands[]` array with name, description, usage, and handler
|
|
4. Rebuild with `make`
|
|
|
|
**Other Ideas for expansion:**
|
|
- File system support
|
|
- Memory management
|
|
- Graphics output
|
|
- Network stack
|
|
- Device drivers
|
|
- Multi-tasking
|
|
|
|
## Resources
|
|
|
|
- [UEFI Specification](https://uefi.org/specifications)
|
|
- [GNU-EFI Documentation](https://sourceforge.net/projects/gnu-efi/)
|
|
- [OSDev Wiki](https://wiki.osdev.org/)
|