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:
- Add support for building bootloaders using
-Zbuild-std
(published asv0.8.1
) - Make
cargo bootimage
usecargo build
instead ofcargo xbuild
(published asv0.9.0
)
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:
- Change 1st stage int 13h addressing (published as
v0.9.6
) - Make bootloader buildable with
-Zbuild-std
(published asv0.9.7
) - Enable rlibc dependency only with
binary
feature (published asv0.9.8
)
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 aBTreeMap
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 aBTreeMap
for each level of the namespace. Because each level of the path can only be 4 characters long (_SB
,PCI0
,ISA
, andCOM1
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
, andDefAnd
. 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:
- Implement
try_lock_weak
for use inlock
loop (published asv0.1.1
) - Upgrade
lock_api
to 0.4.0 (published asv0.2.0
) - Implement
const_spinlock
convenience function (published asv0.2.1
)
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:
- Derive Default for Volatile, WriteOnly and ReadOnly (published as
v0.2.7
) - Remove
Debug
andClone
derives forWriteOnly
(published asv0.3.0
)
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:
- Add a
validate_checksum
method to rsdp (published asv0.9.0
)
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:
- Migrate code from cargo-xbuild to
-Zbuild-std
- Link 'This Month in Rust OSDev' posts in status updates section
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 Zulip chat.