DEV Community

Kushal_Meghani1644
Kushal_Meghani1644

Posted on

Creating a boot-loader from scratch... Meet: RustyBoot!

"Exploring the fascinating world of low-level systems programming by building a bootloader in Rust that can load ELF kernels from EXT filesystems"


Ever wondered what happens in those critical first moments when your computer boots up?

Building a bootloader is one of the most fascinating journeys into low-level systems programming, and doing it in Rust adds memory safety to the mix. Today, I'm excited to share RustyBoot - a single-stage x86 bootloader written entirely in Rust that can load ELF kernels from EXT filesystems.

What is RustyBoot?

RustyBoot is a freestanding x86 bootloader that bridges the gap between your computer's firmware and your operating system kernel. Unlike traditional bootloaders that might rely on assembly or C, RustyBoot leverages Rust's zero-cost abstractions and memory safety guarantees in a no_std environment.

Key Features

  • Pure Rust Implementation: Built with no_std and panic=abort for a truly freestanding environment
  • EXT Filesystem Support: Reads EXT2/EXT3/EXT4 filesystems with direct, single indirect, and double indirect block support
  • ELF32 Kernel Loading: Parses and loads ELF32 executables into memory
  • ATA PIO Disk Driver: Direct hardware communication for disk operations
  • Memory Management: Simple bump allocator managing 1MB to 8MB region
  • VGA Text Console: Classic text-mode output for debugging and status messages

The Architecture

The bootloader follows a clean, modular design that handles the entire boot process:

Hardware Reset → VGA Init → Memory Init → ATA PIO Init
→ MBR Parse → EXT Filesystem → Kernel Discovery
→ ELF Loading → Memory Reservation → Kernel Jump

Core Components

Disk Operations: The ATA PIO driver handles hardware-level disk communication, reading sectors directly from the primary master drive.

Filesystem Layer: The EXT reader validates filesystem magic numbers, handles various block sizes (1KB to 4KB), and navigates directory structures to locate kernel files.

Kernel Loader: Searches common kernel paths (/boot/vmlinuz, /boot/kernel, /kernel, /boot/bzImage) and loads ELF32 PT_LOAD segments to their specified virtual addresses.

Why Rust for Bootloader Development?

Traditional bootloaders are often written in assembly or C, but Rust brings several advantages to low-level systems programming:

Memory Safety Without Runtime Cost

Rust's ownership system prevents common bootloader bugs like buffer overflows and null pointer dereferences - critical in an environment where a crash means a complete system halt.

Zero-Cost Abstractions

Higher-level constructs like iterators and pattern matching compile down to efficient assembly, making the code more readable without performance penalties.

Rich Type System

Rust's enums and structs make it easier to model complex data structures like MBR partition tables and ELF headers safely.

Technical Deep Dive

Building the Project

The build process uses a custom target specification and linker script:

// Target: i686-bootloader.json
{
"llvm-target": "i686-unknown-none",
"data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128",
"arch": "x86",
"target-endian": "little",
"target-pointer-width": "32",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"panic-strategy": "abort",
"disable-redzone": true,
"code-model": "kernel"
}

The linker script places the .text section at 0x8000, ensuring proper memory layout for x86 real mode execution.

Filesystem Implementation

RustyBoot implements a minimal but functional EXT filesystem reader:

// Simplified EXT superblock validation
fn validate_ext_superblock(superblock: &ExtSuperblock) -> Result<(), ExtError> {
if superblock.magic != 0xEF53 {
return Err(ExtError::InvalidMagic);
}

// Reject complex features for simplicity
if superblock.feature_incompat & FEATURE_EXTENTS != 0 {
return Err(ExtError::UnsupportedFeature);
}

Ok(())
}

This approach prioritizes reliability over feature completeness - perfect for early boot environments where simplicity is crucial.

Getting Started

Want to try RustyBoot? Here's how to build and run it:

Install Rust with LLVM tools

  • rustup component add llvm-tools-preview

Build the bootloader

  • make bootloader

Create a test disk image

  • make disk

Run in QEMU

  • make run

The generated disk.img contains the boot sector. To boot a real kernel, attach a drive with an EXT filesystem containing your kernel at one of the supported paths.

Current Limitations and Future Plans

RustyBoot currently has some intentional limitations that keep the codebase focused and educational:

  • 32-bit only: No long mode setup for x86_64
  • Single disk support: Primary master ATA PIO only
  • File size limit: 1MB maximum due to compile-time buffer constraints
  • No advanced EXT features: Extents and 64-bit features not supported

These limitations make RustyBoot perfect for learning and experimentation while keeping the complexity manageable.

The Learning Journey

Building RustyBoot taught me invaluable lessons about:

  • Hardware abstraction: Working directly with ATA controllers and VGA hardware
  • Filesystem internals: Understanding how EXT filesystems organize data on disk
  • Memory management: Implementing allocation in constrained environments
  • Binary formats: Parsing and loading ELF executables
  • Rust in embedded contexts: Using Rust's features in no_std environments

What's Next?

RustyBoot is part of the Rusty-Suite - a collection of systems programming projects in Rust. Future enhancements might include:

  • FAT filesystem support (currently stubbed)
  • x86_64 long mode transitions
  • UEFI compatibility
  • Enhanced error handling and recovery

Join the Journey

Operating systems development in Rust is an exciting and rapidly growing field. Whether you're interested in bootloaders, kernels, or embedded systems, there's never been a better time to explore low-level programming with Rust's safety guarantees.

Check out the RustyBoot repository to explore the code, contribute improvements, or use it as a starting point for your own bootloader adventures.


Have questions about bootloader development or Rust systems programming? Drop them in the comments below! I'd love to discuss the technical details and help others on their own low-level programming journeys.

Top comments (0)