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
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
Announcements, News, and Blog Posts
- Redox OS 0.8.0
- [Talk] FerrOS: Rust-y unikernels on seL4
- Aero, a new modern OS made in rust and is now able to run Xorg
- Tales of the M1 GPU
- Asahi Lina shares her experience with writing a Linux kernel driver for the Apple M1 GPU in Rust.
- Memory Safe Languages in Android 13
- There are now ~1.5 million lines of Rust code in AOSP.
- "Based on this historical vulnerability density, it’s likely that using Rust has already prevented hundreds of vulnerabilities from reaching production."
- Rust Developers Move Ahead With Preparing To Upstream More Code Into The Linux Kernel
In this section, we give an overview of notable changes to the projects hosted under the
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_apicrate 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 fnof 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.tomlanymore, 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
bootloaderlibrary 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
Thanks a lot to the numerous people that tested our beta releases and reported issues!
Maintained by @GabrielMajeri, @nicholasbishop, and @phip1611
- Make the
cstr16!macro usable in const contexts
- const fn for trivial getters where possible
- Support ISA-specific
- Allow uefi-services to work when the "logger" feature is disabled in uefi
- Unicode collation
- Add structs for all device path node types and a new
- Implement additional
- Publish new releases
- const fn wherever possible
- rename crate features
- Several small improvements to EqStrUntilNul
Directory::read_entry_boxedplus common abstraction
- Implement Error trait for
get_boxed_info_inthat use the
- Add uefi/README.md
- Install UEFI targets via rustup
- book: Add a graphics example
- documentation and code improvements for Status, Error, and read()
- Clean up crate feature list documentation
unstablefeature and improve CI for feature flags
- Doc updates: add "Running on Hardware" to book and drop BUILDING.md
- Don't explicitly require compiler-builtins(-mem)
- Add temporary workaround for yanked dependency
- workspace: uefi (main library) is in a dedicated directory now
- Copy LICENSE to the new uefi directory
- Improve clap help for
- several unrelated cleanups
- uefi-test-runner: Assume that we're running in the special QEMU env
- Simplify serial usage in test-runner and check that tests completed
- clippy: require must_use_candidate lint
- doc: add '--document-private-items' to
cargo xtask doc
- test-runner: Make some tests stricter
- test-runner: Open serial device in exclusive mode
- Make GOP test work on aarch64
Thanks to @blitz, @YtvwlD, @timrobertsdev, @NathanRoyer, and @d-sonuga for their contributions!
Maintained by @phil-opp and @jamesmunns
We merged the following tooling changes this month to make the crate more reliable:
- Detect fragmentation when fuzzing
- Fix miri test failures caused by address unleaking of heap data in tests
Thanks to @evanrichter for their contribution!
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.
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.
(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
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!
(Section written by @mkroening)
While working on the
libhermit-rs kernel, I moved the synchronization primitives targeted at kernel development into a separate crate:
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
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.
(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
takes a virtual address as input and shows you the indices the hardware will use. You can find the
utility on crates.io.
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 gitter channel.