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
- 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
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 theentry_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 implementedconst 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. Inv0.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
- Make the
cstr16!
macro usable in const contexts - const fn for trivial getters where possible
- Support ISA-specific
MemoryAttribute
s inMemoryDescriptor
s - 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
DevicePathBuilder
- Implement additional
BootServices
functions - Publish new releases
- const fn wherever possible
- rename crate features
- Several small improvements to EqStrUntilNul
TryFrom<core::ffi::CStr>
implementation forCStr8
Directory::read_entry_boxed
plus common abstractionmake_boxed
- Implement Error trait for
uefi::Error
- Added
read_entry_boxed_in
andget_boxed_info_in
that use theallocator_api
Docs
- 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
- Add
unstable
feature and improve CI for feature flags - Doc updates: add "Running on Hardware" to book and drop BUILDING.md
Internal
- Update
mbrman
to 0.5.0 - 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
--target
- 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!
linked-list-allocator
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!
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
andLazy
based ongeneric_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.