+++
title = "Writing an OS in pure Rust"
date = 2018-03-09
aliases = ["news/2018-03-09-pure-rust"]
+++

Over the past six months we've been working on a second edition of this blog. Our goals for this new version are [numerous] and we are still not done yet, but today we reached a major milestone: It is now possible to build the OS natively on Windows, macOS, and Linux **without any non-Rust dependendencies**.

[numerous]: https://github.com/phil-opp/blog_os/issues/360

<!-- more -->

The [first edition] required several C-tools for building:

[first edition]: @/edition-1/_index.md

- We used the [`GRUB`] bootloader for booting our kernel. To create a bootable disk/CD image we used the [`grub-mkrescue`] tool, which is very difficult to get to run on Windows.
- The [`xorriso`] program was also required, because it is used by `grub-mkrescue`.
- GRUB only boots to protected mode, so we needed some assembly code for [entering long mode]. For building the assembly code, we used the [`nasm`] assembler.
- We used the GNU linker [`ld`] for linking together the assembly files with the rust code, using a custom [linker script].
- Finally, we used [`make`] for automating the various build steps (assembling, compiling the Rust code, linking, invoking `grub-mkrescue`).

[`GRUB`]: https://www.gnu.org/software/grub/
[`grub-mkrescue`]: https://www.gnu.org/software/grub/manual/grub/html_node/Invoking-grub_002dmkrescue.html
[`xorriso`]: https://www.gnu.org/software/xorriso/
[entering long mode]: @/edition-1/posts/02-entering-longmode/index.md
[`nasm`]: https://www.nasm.us/xdoc/2.13.03/html/nasmdoc1.html
[`ld`]: https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html
[linker script]: https://sourceware.org/binutils/docs/ld/Scripts.html
[`make`]: https://www.gnu.org/software/make/

We got lots of feedback that this setup was difficult to get running [under macOS] and Windows. As a workaround, we [added support for docker], but that still required users to install and understand an additional dependency. So when we decided to create a second edition of the blog - originally because the order of posts led to jumps in difficulty - we thought about how we could avoid these C-dependencies.

[under macOS]: https://github.com/phil-opp/blog_os/issues/55
[added support for docker]: https://github.com/phil-opp/blog_os/pull/373

There are lots of alternatives to `make`, including some Rust tools such as [just] and [cargo-make]. Avoiding `nasm` is also possible by using Rust's [`global_asm`] feature instead. So there are only two problems left: the bootloader and the linker.

[just]: https://github.com/casey/just
[cargo-make]: https://sagiegurari.github.io/cargo-make/
[`global_asm`]: https://doc.rust-lang.org/stable/core/arch/macro.global_asm.html

## A custom Bootloader
To avoid the dependency on GRUB and to make things more ergonomic, we decided to write [our own bootloader] using Rust's [`global_asm`] feature. This way, the kernel can be significantly simplified, since the switch to long mode and the initial page table layout can already be done in the bootloader. Thus, we can avoid the initial assembly level blog posts in the second edition and directly start with high level Rust code.

[our own bootloader]: https://github.com/rust-osdev/bootloader

The bootloader is still an early prototype, but it is already capable of switching to long mode and loading the kernel in form of an 64-bit ELF binary. It also performs the correct page table mapping (with the correct read/write/execute permissions) as it's specified in the ELF file and creates an initial physical memory map.

The plan for the future is to make the bootloader more stable, add documentation, and ultimately add a “Writing a Bootloader” series to the blog, which explains in detail how the bootloader works.

## Linking with LLD
With our custom bootloader in place, the last remaining problem is platform independent linking. Fortunately there is [`LLD`], the cross-platform linker from the LLVM project, which is already very stable for the `x86` architecture. As a bonus, `LLD` is [now shipped with Rust], which means that it can be used without any extra installation.

[`LLD`]: https://lld.llvm.org/
[now shipped with Rust]: https://github.com/rust-lang/rust/pull/48125

## The new Posts
The second edition is already live at [https://os.phil-opp.com/second-edition]. Please tell us if you have any feedback on the new posts! We're planning to move over the content from the [first edition] iteratively, in a different order and with various other improvements.

[https://os.phil-opp.com/second-edition]: @/edition-2/_index.md

Many thanks to everyone who helped to make Rust an even better language for OS development!
