Rust OSDev Operating System Development in Rust

This Month in Rust OSDev (December 2021)

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.

Project Updates

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

x86_64

The x86_64 crate provides various abstractions for x86_64 systems, including wrappers for CPU instructions, access to processor-specific registers, and abstraction types for architecture-specific structures such as page tables and descriptor tables.

We merged the following changes in December:

Thanks to @toku-sa-n for their contribution!

bootloader

The bootloader crate implements a custom Rust-based bootloader for easy loading of 64-bit ELF executables.

This month, we released new patch versions for both v0.9 and v0.10 to fix the asm! macro imports on the latest Rust nightlies:

We also continued the work on the upcoming v0.11 version, which will feature the following improvements:

  • Configuration via Rust structs and the entry_point macro, instead of a [package.metadata.bootloader] table in the Cargo.toml.
    • The config data is serialized at compile time and put into a separate ELF section of the kernel executable.
    • This makes it possible to read the config data dynamically when loading the kernel, so we no longer need to recompile the bootloader on config changes.
    • The build process is also simplified as we don't need to read the kernel's Cargo.toml anymore.
  • Instead of including the kernel ELF file using the include_bytes macro, we read the file dynamically from disk during the boot process.
    • The boot image is now a proper FAT partition for both UEFI and BIOS. The kernel file is simply copied to this partition.
    • In combination with the new config mechanism, the dynamic loading means that the bootloader only needs to be compiled once.
  • The bootloader crate is split into three subcrates:
    • an API crate that defines the configuration and boot information structs, and provides the entry_point macro (this will be used by kernels)
    • an implementation crate that contains the actual BIOS and UEFI bootloader code
    • a builder crate that allows to turn kernel ELF files into bootable disk images
      • includes the compiled implementation crate, either by including a precompiled binary or through cargo's upcoming artifact dependencies feature

The new configuration system is already done and working for both the BIOS and UEFI implementations. For UEFI, we also implemented the kernel loading from a FAT partition already. Unfortunately, this part is more challenging for the BIOS implementation since the loading needs to happen in 16-bit real mode (as it requires calling functions of the BIOS). Parsing a FAT filesystem is not easy using assembly code, so we're currently working on porting all the lower boot stages to Rust. This includes the boot sector, which needs to fit into 448 bytes, so we need some trickery to get a Rust executable that is small enough.

acpi

The acpi repository contains crates for parsing the ACPI tables – data structures that the firmware of modern computers use to relay information about the hardware to the OS.

December was a fairly quiet month, but an important bug-fix landed that corrected the way we handled _CRS objects in a structure called the _PRT, which are found on PCI root bridges and tell the OS how interrupt pins on PCI devices have been routed to the platform's interrupt controller. Each pin can be hardwired to a specific interrupt, or more commonly, can be dynamically assigned using a 'Link Object' through a set of control methods: _PRS, _CRS, _SRS, and _DIS. However, many platforms implement Link Objects that actually hardcode the interrupts (including QEMU) and this is where the bug slipped in: _CRS was being evaluated as a hardcoded object. We now treat these objects correctly as control methods, supporting properly-configured tables. (published as aml v0.16.1)

Thanks to @Dentosal for this contribution!

uefi-rs

The uefi crate provides safe and performant wrappers for UEFI, the successor to the BIOS.

We merged the following PRs this month:

Thanks to @StevenDoesStuffs and @toku-sa-n for their contributions!

uart_16550

The uart_16550 crate provides basic support for serial port I/O for 16550-compatible UARTs. We merged the following changes this month:

Thanks to @olivercalder for this contribution and @Kazurin-775 for reporting this problem!

Call for Participation

Want to contribute to a Rust OSDev project, but don't know where to start? Pick up one of these outstanding issues in one of our projects and get started!

No tasks were proposed for this section.

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.

metta-systems/vesper

(Section written by @berkus)

Vesper is a capability-based single-address-space nanokernel. This means it is aiming to be small, to provide only isolation primitives; at the same time SAS makes it a lot easier to perform cross-process operations (because all addresses are the same across all processes). It uses capabilities to provide security for such operations, so that unauthorized processes will not be able to intervene in legitimate traffic.

The kernel is in very early stages of development, while I am building up tooling support to make future development fast and painless. This is my second post here and as usual, I will link directly to my blog for more details. Read the full article here.

Just a note: since features described in the article are not fully finalized, they are not merged to the main development branch yet and live in their own branch, which is subject to frequent rebases. Caveat emptor!

rusty-hermit

(Section written by @stlankes)

RustyHermit is a unikernel targeting a scalable and predictable runtime for high-performance and cloud computing.

This month, we integrated a virtual i/o device driver, which is based on memory mapped i/o and doesn't depend on PCI device specification. For instance, micro VMs like Firecracker and Qemu's microvm machine type don't support the PCI specification to accelerate the boot time and to improve the performance. With this device driver, rusty-hermit is able to run on Qemu's microvm platform. We are working to support Firecracker in the near future.

phil-opp/blog_os

(Section written by @phil-opp)

This month, we merged a small translation improvement to the Writing an OS in Rust blog:

Thanks to @TisnKu for this contribution!

My personal focus this month has been on the new bootloader version mentioned above, which I plan to use for the third edition of the blog. I'm also thinking about writing a post about creating a basic BIOS bootloader in Rust if I can find the time.

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