Rust OSDev Operating System Development in Rust

This Month in Rust OSDev (July 2020)

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.

Project Updates

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

bootimage

The bootimage tool allows the creation of bootable disk images for bootloader-based kernels. It also provides a runner executable for cargo to make cargo run and cargo test work using QEMU. In July, the crate was updated to work with cargo's own build-std feature instead of relying on the cargo-xbuild crate:

bootloader

The bootloader crate implements a custom Rust-based bootloader for easy loading of 64-bit ELF executables. In July, we switched the crate from cargo-xbuild to the build-std feature of cargo and fixed a bug that prevented booting in VirtualBox:

Thanks to @rsribeiro for their contribution!

We also made some progress on adding UEFI support to the bootloader. Our prototype is now able to set up a pixel-based framebuffer, map a given kernel ELF file into virtual memory, and then pass control to its entry point. The next steps are the construction of the boot information structure, including a memory map. You can find a link to the code and the build instructions in this comment.

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. This month saw some substantial improvements to our AML handling:

  • Objects defined by AML tables exist within a namespace, with objects referred to by paths such as \_SB.PCI0.ISA.COM1. Until now, we represented this namespace using a BTreeMap between the path (allocated on the heap) and a handle to the object, meaning that there was both a heap-allocated container, and a heap allocation for every single path within the namespace. In this PR, we moved the library to use a new representation that has a BTreeMap for each level of the namespace. Because each level of the path can only be 4 characters long (_SB, PCI0, ISA, and COM1 are the name segments in the example above), storing the path of each level no longer requires a heap allocation per object, which reduces the heap-burden of the library significantly.
  • Some more opcodes were implemented: Target, DefShiftLeft, DefShiftRight, DefLOr, and DefAnd. These all appear in QEMU's tables.
  • A fairly large PR was merged that provides the ability to traverse the namespace and initialize devices - this is a mechanism that ACPI provides that allows an OS to initialize hardware that it does not have drivers for, and is a compulsory step in getting modern chipsets to function properly. This required us to build up a lot of functionality, including namespace traversal, reading and writing from operation regions, recursively invoking control methods, and asking the OS to perform hardware configuration for us (such as reading and writing to IO ports and PCI configuration space). There is still a lot of work in getting all of this working robustly, but this is a great start.

uefi-rs

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

The major changes which happened in this month are:

  • We've tested out support for AArch64. No updates to the code are needed, just add a custom target file for 64-bit ARM UEFI and then compile your project with it.
  • The LoadedImage protocol now exposes the handle for the device where the binary is stored.
  • Our CI is now green again! There is only one test which breaks QEMU, and it's going to stay disabled until it gets fixed.
  • Building the repository no longer requires cargo-xbuild, we've switched to nightly Cargo's build-std feature.
  • Updated documentation in various places.

spinning_top

The spinning_top crate provides a simple spinlock implementation based on the abstractions of the lock_api crate. We created the crate to provide an alternative to the no-longer maintained spin crate. In July, the crate received the following updates:

Thanks to @akiekintveld for their contributions!

volatile

The volatile crate provides safe wrapper types for implementing volatile read and write operations. The crate received the following changes this month:

Thanks to @Freax13 for their contributions!

We are also considering a complete rewrite of the crate to wrap references instead of values directly. The main advantage of this is that it makes working with slices possible. See the pull request for details.

multiboot2

The multiboot2 crate provides abstraction types for the boot information of multiboot2 bootloaders. In July, we merged a change that makes the checksum field of the RSDP tag more useful:

Thanks to @dlrobertson for this contribution!

cargo-xbuild

The cargo-xbuild project provides cargo command wrappers to cross-compile the sysroot crates core and alloc. While there were no updates to the crate itself in July, we added a guide on how to switch from cargo-xbuild to cargo's own build-std feature to the Readme. You can read it here.

Personal Projects

In this section, we describe updates to personal 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.

IsaacWoods/pebble

(Section written by @IsaacWoods)

Between my work on acpi and university commitments, I have not had much time to work on Pebble this month, but some small clean-ups were made:

  • The migration from Travis CI to Github Actions was completed, allowing Pebble to be emulated on CI.
  • Pebble uses a HAL (hardware abstraction layer) to separate hardware access from kernel logic. Various parts of the x86_64 implementation of the HAL were made common to support code-reuse across architectures.
  • Some tests were added to the buddy allocator (Pebble's physical memory manager). This was to rule out physical memory allocation as the cause of a bug where user stacks are occasionally corrupted at the userspace-kernel boundary, which unfortunately has still not been fixed.
  • Our algorithm for efficiently mapping arbitrary areas was rewritten and extended to support 1GiB pages.
  • Work has started on a topology layer - data structures that represent features of the platform such as processors, caches, NUMA nodes, and microarchitectural information. This will help in allowing Pebble to make more intelligent decisions about scheduling and resource usage in the future.

phil-opp/blog_os

(Section written by @phil-opp)

The main change this month was the migration from cargo-xbuild to the build-std feature of cargo. This means that we can now use the normal cargo build/cargo run/cargo test commands for our kernel 🎉.

The full list of notable changes is:

There were also some contributions this month that fixed typos and updated links. Thanks a lot to all contributors!

For the next weeks/months, my plan is to finish the UEFI bootloader implementation and then adjust the blog to work with both the BIOS and UEFI bootloaders. Among other things, this will require that we switch from the VGA text buffer to a pixel-based framebuffer because the VGA text mode is not available with UEFI. While this makes things more complicated (we need to do some simple font rendering and add slice support to volatile crate), it will allow us to create our own graphical user interface, render a mouse pointer, or display images.

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 gitter channel.