6

OS in Rust: Building kernel for custom target: Part-4

 3 years ago
source link: https://blog.knoldus.com/os-in-rust-building-kernel-for-custom-target-part-4/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
cropped-knoldus-blog.jpg

OS in Rust: Building kernel for custom target: Part-4

Reading Time: 4 minutes

This series pertains to create a basic Operating System using Rust Programming Language. This series aims to learn and understand the basics of Operating System.
Through this series, you will get some ideas about the internal components of Operating System and how they interact with each other.

This article pertains to building a custom kernel for the custom target that we created in our previous post.

This image has an empty alt attribute; its file name is images-1.jpeg

To building our kernel we need to follow a few steps:

  • Recompiling core library
  • Enabling compiler-builtins-mem feature
  • Setting-up default target

Before proceeding further let’s brush-up our understanding of the custom target. So, here is the JSON file(named x86_64-os-in-rust.json) that we created in our previous post:

{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "none",
  "executables": true,
  "linker-flavor": "ld.lld",
  "linker": "rust-lld",
  "panic-strategy": "abort",
  "disable-redzone": true,
  "features": "-mmx,-sse,+soft-float"
}

A quick update on this, we’ve configured the target for x86_64-unknown-none where the architecture is x86_64 and our OS(operating system) is none because we don’t need any underlying operating system for our kernel. To know more about this custom target file, please have a look at the previous blog of this series.

Alright!!! we brushed-up the details of our previous article, now let’s dive into the scope of this one.
Here we’re trying to build our kernel for the custom target. And for building any Rust code, cargo(build tool) is ready for us.

Now let’s fire the build command for the custom target:

Oops!!! we got an error. Okay, so let’s understand why we got this?
The error tells us that the Rust compiler can’t find the core library. So the very first question that comes into our mind is Why we need this? Right?
So the reason for this library is it contains basic Rust types such as ResultOption, and iterators, and one more thing it is implicitly linked to all no_std crates as well.

But here is a problem, as we are building our kernel for our custom target, and the core library is distributed together with the Rust compiler as a precompiled library. So it is only valid for supported host triples (e.g., x86_64-unknown-linux-gnu) but not for our custom target.

Now we only one option left, we need to recompile the core library for our target.

Recompile core library

To recompile core, we have to use cargo’s feature built-std . It allows us to recompile core and other standard library crates. And as this feature is in its very early stages of development so this would available for us in nightly version only.

In order to use this feature we need to create a cargo configuration file .cargo/config.toml and need to put this on that file:

[unstable]
build-std = ["core", "compiler_builtins"]

Through this the cargo will recompile the core and compile_builtins libraries.
Another thing comes here is if we want to use this feature, then we need to have the source code for the standard library available, and at this time the only supported method of doing so is to add the rust-src rust’s rustup component:

rustup component add rust-src

Now let’s try to build our kernel again:

This image has an empty alt attribute; its file name is screenshot-from-2020-11-27-21-48-34.png

In the output, we can see that cargo recompiles corerustc-std-workspace-core, and compiler_builtins libraries for our custom target. And we build our kernel successfully now the next stage is to provide some kind of memory-related built-ins.

Enable compiler-builtins-mem feature

Built-in functions are available for all systems and most of these functions are provided by the compiler_builtins crate that we just recompiled.
The memory-related functions in the compiler_builtins are:

  • memset: sets all bytes in a memory block to a given value,
  • memcpy: copies one memory block to another,
  • memcmp: compares two memory blocks

These functions will be needed when we add some more code to it, but as of now, they don’t require us to compile our kernel.
So as these functions are available for all systems and since we can’t link to the C library of the operating system, we have to figure out another way to provide these functions to the compiler.
There are two approaches to provide these functions to our compiler:

  • Either we have to write our implementation for these functions,
  • Or we can enable the disabled feature provided by the compiler_builtins crate because it already contains implementations for all the needed functions. They are just disabled by default to not collide with the implementations from the C library.

So we’ll go with the second approach because this would be the best-suited approach for this time.

Okay, to enable these functions by setting cargo’s build-std-features flag to ["compiler-builtins-mem"] . So to do this, we have to configure this in the unstable table inside the .cargo/config.toml file. Like this:

[unstable]
build-std-features = ["compiler-builtins-mem"]

Our config.toml file will look like this:

Now our last step for this article is to setting-up the target as default for our kernel. As we are explicitly providing --target parameter with cargo build command. So to avoid this we can configure it as default by providing instructions in our config.toml file like this:

[build]
target = "x86_64-os-in-rust.json"

From now onwards, whenever we will trigger the cargo build command, it will automatically build a kernel for our defined target.

That’s all for this article, thanks for reading.

In the next part, we will try to run our kernel and print something on the screen.

Stay tuned!!!

References:

Blogs of this series:

If you want to read more content like this?  Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7 .

Knoldus-blog-footer-image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK