Rust OSDev Operating System Development in Rust

This Month in Rust OSDev: November 2022

Welcome to a new issue of "This Month in Rust OSDev". In these posts, we give a regular overview of notable changes in the Rust operating system development ecosystem.

This series is openly developed on GitHub. Feel free to open pull requests there with content you would like to see in the next issue. If you find some issues on this page, please report them by creating an issue or using our comment form at the bottom of this page.

We have some new sections this month, we hope you like the content!

Infrastructure and Tooling

In this section, we collect recent updates to rustc, cargo, and other tooling that are relevant to Rust OS development.

UEFI Targets are now Tier 2

(Section written by @nicholasbishop)

The MCP to raise the three UEFI targets to tier 2 by @dvdhrm was recently approved. Following that we merged a PR to dist builds of the UEFI targets so that you can install them via rustup (e.g. rustup target add --toolchain nightly x86_64-unknown-uefi), and a PR to add an initial QEMU test for the x86_64 UEFI target to help prevent regressions from landing.

The initial nightlies containing the prebuilt UEFI targets revealed some issues in compiler_builtins which we fixed and are in the 0.1.84 release. Finally, we changed the C compiler for the UEFI targets from gcc to clang, which resolved some linker problems. As of the 2022-11-22 nightly, the three UEFI targets should be fully usable, which means you no longer need to use the unstable -Zbuild-std feature.

Announcements, News, and Blog Posts

rust-osdev Projects

In this section, we give an overview of notable changes to the projects hosted under the rust-osdev organization.

bootloader

Maintained by @phil-opp

Just a few days ago, we finally released version 0.11.0 of the the bootloader crate. This release is a major rewrite with various new features and also breaking changes:

  • Separate API crate: The bootloader is now split into two parts: A bootloader_api crate to make kernels loadable by the bootloader and the actual bootloader implementation. This makes the build process for kernels much easier and faster.
  • New config system: Instead of configuring the bootloader via a special table in the Cargo.toml, the configuration now happens through a normal Rust struct, which is part of the entry_point! macro. The macro then serializes the config struct at compile time and places it in a special ELF output section. The compile time serialization happens through a manually implemented const fn of the config struct.
  • Load the kernel at runtime: Up to version 0.10, the bootloader used to link the kernel at compile time, which required recompiling the bootloader whenever the kernel was modified. In v0.11, we now load both the kernel and the configuration at runtime, so no rebuilding of the bootloader is needed anymore.
  • Split into sub-crates: Since the bootloader build process does not need access to the kernel executable or its Cargo.toml anymore, we can build the different parts of the bootloader independently. For example, the BIOS boot sector is now a separate crate, and the UEFI bootloader is too. (We plan to make them proper artifact dependencies as soon as they're allowed on crates.io.)
  • Library to create disk images: To create an abstraction the complex build steps of the different bootloader executables, we compile them inside cargo build scripts. At the top level, we provide a bootloader library crate, which compiles everything as part of its build script. This library includes functions for creating BIOS and UEFI disk images for a given kernel. These functions can be used e.g. from a builder crate or a build script of the downstream operating system.

See our README for detailed usage instructions. We also created migration guides that explain how to update from v0.9 and v0.10.

Thanks a lot to the numerous people that tested our beta releases and reported issues!

uefi-rs

Maintained by @GabrielMajeri, @nicholasbishop, and @phip1611

Features

Docs

Internal

Thanks to @blitz, @YtvwlD, @timrobertsdev, @NathanRoyer, and @d-sonuga for their contributions!

linked-list-allocator

Maintained by @phil-opp and @jamesmunns

We merged the following tooling changes this month to make the crate more reliable:

Thanks to @evanrichter for their contribution!

acpi

Maintained by @IsaacWoods

Thanks to @semiviral for their contribution!

Call for Participation

Want to contribute to a Rust OSDev project, but don't know where to start? Help with one of these outstanding issues!

No tasks were proposed for this section this month.

If you maintain a Rust project related to operating system development and are looking for contributors, especially for tasks suited to people getting started in this space, please create a PR against the next branch with the tasks you want to include in the next issue.

Other Projects

In this section, we describe updates to Rust OS projects that are not directly related to the rust-osdev organization. Feel free to create a pull request with the updates of your OS project for the next post.

bendudson/EuraliOS

(Section written by @bendudson)

EuraliOS is a hobby multitasking operating system written in Rust. It's based on a microkernel ("Merriwig") that provides on-demand paging, stack and heap memory management for multi-threaded user processes. Drivers run in Ring 3 and communication between processes is by Rendezvous message passing. Each process can have its own virtual file system, enabling multiple users to be isolated from each other.

This still has many rough edges and doesn't have many drivers: EuraliOS only has ramdisk storage, but does have a TCP stack thanks to the smoltcp crate. The only user programs are a simple shell and a Gopher client; I'm trying to port the kibi text editor but have a lot of work to do on the standard library.

This was based on Phil's blog and uses many rust-osdev crates including x86_64, bootloader and vga. Thanks to Phil and Rust-OSdev contributors for all their work supporting this community!

I've tried to document the development steps and hope these are useful for others, particularly the sections on getting into Ring 3, implementing syscalls and switching stacks with swapgs. Suggestions for improvement welcome!

hermitcore/hermit-sync

(Section written by @mkroening)

While working on the libhermit-rs kernel, I moved the synchronization primitives targeted at kernel development into a separate crate: hermit-sync. Whilst I was there, I also enhanced the code and made it independent from libhermit, so the code can now be used in other projects as well; at least x86_64 and aarch64 ones for the moment.

The crate contains the following features:

  • a function for running a closure without interrupts
  • a simple spinlock with exponential backoff
  • a fair ticket lock with exponential backoff
  • OnceCell and Lazy based on generic_once_cell (another recent project of mine)

All of these primitives are available with and without interrupt safety. See the API docs for more details.

Any feedback is very welcome of course.

phip1611/paging-calculator

(Section written by @phip1611)

I worked on setting up page tables in a low-level project and noticed that there is lots of room for confusion. For example, x86 has at least four different modes of paging: 32-bit paging, 32-bit paging with PAE, 64-bit 4-level paging, and 64-bit 5-level paging. 32-bit without PAE paging uses 10 bits to index into a page table while 64-bit paging uses 9 bits to index into the table of each level. To demystify the magic a little, I created a CLI utility called paging-calculator that takes a virtual address as input and shows you the indices the hardware will use. You can find the utility on crates.io.

Join Us?

Are you interested in Rust-based operating system development? Our rust-osdev organization is always open to new members and new projects. Just let us know if you want to join! A good way for getting in touch is our Zulip chat.

Comments