This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

My Minimal Rust Operating System

1 - Introduction

What I am doing and why, as well as the initial setup before starting the tutorials.

What am I doing?

I am going through the Writing an OS in Rust guides created by Phil Oppermann.

I am hosting the source code in this repo. For each part of the original guide I will create an article on what I did and any notable changes or thoughts in regards to what was originally done, I will also create a git branch to save what I had done for each part of the guide.

Why am I doing this?

I want to learn lower level systems programming and I want to learn it through Rust as I am an interested in learning the capapilities of the language and if I want to switch to C/C++ it will be easier learning the fundamentals through Rust first.

What has been setup before starting the tutorial.

  • Created the initial Rust barebones project.
  • Since I use the Nix package manager I have created a Flake.nix that I will use with nix-direnv to control my developer environments
  • I have created the repository on Github here and committed all the current changes to it.

Next

Now I can start with the guide and will leave any updates on further pages.

2 - Part 1 - A Freestanding Rust Binary

Running through the first part with A Freestanding Rust Binary

Rust Analyzer and no_std

Starting this guide everything appears to be the working as intended with the guide. So far the only thing worth noting is that the Rust Analyzer is throwing errors regarding the use of the custom panic implementation as it still refers to the standard library despite the use of #![no_std].

Looking online there does appear to be some possible fixes and I may apply them if none of what is applied in future tutorials fixes it.

Nix issues with a different build targets

For my developer environment I use nix-direnv with a flake.nix which will install and setup any special packages as well as the Rust version I want.

Previously I was using the nightly version of Rust in order to use no_std however I couldn’t install extra targets though the flake.nix directly. Luckily the flake was already setup to install Rust according to a supplied rust-toolchain.toml file.

So I created the following rust-toolchain.toml file and committed it to git so Nix could properly detect it.

[toolchain]
channel = "nightly-2024-12-20"
components = ["rust-src", "rustfmt", "clippy"]
targets = ["thumbv7em-none-eabihf"]
profile = "default"  

When that was complete direnv reloaded and I was able to cross compile the existing example code.

3 - Part 2 - A Minimal Rust Kernel

Running through part 2 of making a rust os: A Minimal Rust Kernel

Changes made before starting part 2 of the tutorial

Before starting part two I noticed that there were two issues I had to look at.

Unsafe no_mangle

When attempting to build with the thumbv7em-none-eabihf target it was getting an error saying that #[no_mangle] needed to be wrapped in an unsafe block. The original guide made no mention of this, however after a quick google search I was able to find the relevant RFC to consider some attributes unsafe here. I looked at the linked PR and found that the change was made to nightly as recently as Oct 31 2024 and since I was on a nightly version from the end of December 2024 it means it affected me.

I then made the change to the code like so

// main.rs
#![no_std]
#![no_main]
use core::panic::PanicInfo;

#[unsafe(no_mangle)]
pub extern "C" fn _start() -> ! {
    loop {}
}

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

Rust Analyzer still referencing the std library

Rust analyzer was giving false-positive errors as it still references the std library despite the use of #![no_std]. In order to fix this I would need to tell rust analyzer to not check on all targets. Since I use the Helix modal editor for dev work I can create a local languages.toml file with any changes that are relevant for the projects.

After creating .helix/languages.toml in the base of my repo and adding the following contents rust analyzer no longer reported errors based on using the std library.

[language-server.rust-analyzer.config.check]
allTargets = false
targets = "aarch64-apple-darwin"

Actually working on Part 2

Thankfully while working on part two there were no issues involving my Nix setup or using a newer version. I only had to add the llvm-tools-preview to my rust-toolchain.toml file so that the feature was added as a part of my dev shell and then add cargo-bootimage to the list of Nix packages that should be available as well.

Thoughts

  • I had a look at the later versions of the bootloader library in case trying to use it would be worth it but as of right now it seems too large a task. Will possibly look at it later when I have more experience with OS dev.