This is the multi-page printable view of this section. Click here to print.
My Minimal Rust Operating System
1 - Introduction
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
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
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.