Getting Started
Build MinimalOS NextGen from source, create a bootable ISO, and run it in QEMU.
Table of contents
Prerequisites #
Rust Toolchain
MinimalOS uses Rust nightly (configured automatically via rust-toolchain.toml):
# Install rustup if you haven't already
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# The nightly toolchain and rust-src component install automatically
# when you run cargo in the project directory
The toolchain file pins the exact nightly version and includes the rust-src component (required for building core/alloc for bare metal).
System Packages
On Ubuntu/Debian:
sudo apt install xorriso qemu-system-x86 git make
On Fedora:
sudo dnf install xorriso qemu-system-x86 git make
On Arch Linux:
sudo pacman -S libisoburn qemu-system-x86 git make
| Package | Purpose |
|---|---|
xorriso | Creates bootable ISO images |
qemu-system-x86 | x86_64 emulator for testing |
git | Downloads the Limine bootloader |
make | Orchestrates the build |
UEFI Firmware (for QEMU)
QEMU needs OVMF firmware for UEFI boot:
# Ubuntu/Debian
sudo apt install ovmf
# The firmware is expected at /usr/share/qemu/OVMF.fd
# or /usr/share/OVMF/OVMF_CODE.fd
Building #
Debug Build
make
Builds the kernel with debug symbols and minimal optimization for development. Dependencies are still optimized (opt-level = 2) for faster boot.
Release Build
make release
Builds with full optimizations: opt-level = 2, link-time optimization (LTO), single codegen unit. Produces a smaller, faster kernel binary.
Create Bootable ISO
make iso # Debug ISO → target/minimalos-debug.iso
make iso-release # Release ISO → target/minimalos-release.iso
The ISO creation process:
- Downloads and compiles the Limine bootloader (cached in
target/limine-src/) - Copies the kernel ELF binary and boot config into an ISO directory structure
- Uses
xorrisoto create a hybrid BIOS/UEFI bootable ISO
Running in QEMU #
Interactive (with display)
make run # Debug build
make run-release # Release build
This opens a QEMU window showing the framebuffer console. Serial output goes to the terminal.
Headless (CI-friendly)
make run-headless
Boots without a display window. Serial output is captured to target/serial-output.log. QEMU auto-terminates after 5 seconds. Useful for automated testing.
Manual QEMU Command
qemu-system-x86_64 \
-M q35 \
-m 512M \
-cpu Goldmont \
-smp 4 \
-bios /usr/share/qemu/OVMF.fd \
-cdrom target/minimalos-debug.iso \
-serial stdio \
-no-reboot
| Flag | Purpose |
|---|---|
-M q35 | Modern chipset (PCIe, AHCI) |
-m 512M | 512 MB RAM (approximate N3710 test config) |
-cpu Goldmont | Closest QEMU CPU model to Airmont |
-smp 4 | 4 CPU cores (matches N3710) |
-serial stdio | Serial output to terminal |
-no-reboot | Don't reboot on triple fault — hang for debugging |
Expected Boot Output #
A successful boot produces serial output similar to:
==========================================================
MinimalOS NextGen v0.1.0
Capability-based microkernel for x86_64
==========================================================
[boot] HHDM offset: 0xFFFF800000000000
[boot] Kernel physical base: 0x00200000
[boot] Kernel virtual base: 0xFFFFFFFF80200000
[boot] Kernel size: XX KiB (Y pages)
[boot] Sections:
.text: ...
.rodata: ...
.data: ...
.bss: ...
[boot] Physical memory map (N entries):
...
[init] Phase 3: Memory management
[pmm] XXXXX total frames, XXXX used, XXXXX free (498 MiB free)
[heap] Test allocation OK: [42, 1337, 3735928559] (heap used: 32 bytes)
[heap] After drop: 0 bytes used / 256 KiB total
[vmm] Page table infrastructure ready (CR3 switch deferred to Sprint 3)
==========================================================
Sprint 2 complete — memory management initialized!
==========================================================
Project Structure #
graph TD
Root["MinimalOS/"] --> Cargo[".cargo/config.toml"]
Root --> GH[".github/workflows/"]
Root --> Boot["boot/limine.conf"]
Root --> Docs["docs/"]
Root --> Kernel["kernel/"]
Root --> CRoot["Cargo.toml"]
Root --> MK["Makefile"]
Root --> RT["rust-toolchain.toml"]
Kernel --> KCargo["Cargo.toml"]
Kernel --> Linker["linker.ld"]
Kernel --> Src["src/"]
Src --> Main["main.rs"]
Src --> Arch["arch/x86_64/"]
Src --> Drivers["drivers/"]
Src --> Memory["memory/"]
Src --> Sync["sync/"]
Src --> Util["util/"]
Makefile Targets #
| Target | Description |
|---|---|
make | Build kernel (debug) |
make release | Build kernel (release, LTO) |
make iso | Build + create bootable ISO (debug) |
make iso-release | Build + create bootable ISO (release) |
make run | Build + ISO + boot in QEMU (debug) |
make run-release | Build + ISO + boot in QEMU (release) |
make run-headless | Headless QEMU boot, serial to file |
make clean | Remove build artifacts |
make distclean | Remove everything including Limine |
make help | Show all targets |
Continuous Integration #
The project includes a GitHub Actions workflow (.github/workflows/build.yml) that:
- Builds the kernel in both debug and release modes
- Creates a bootable ISO
- Uploads the ISO as a build artifact
- On version tags (
v*): creates a GitHub Release with the ISO and SHA256 checksum