From b8667c45dde0a0ef4c2b4702a6a63ccff962fcd3 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sat, 6 Apr 2019 16:46:05 +0200 Subject: [PATCH 1/2] Update "Minimal Rust Kernel" to new bootloader 0.5.1 and bootimage 0.7.2 --- .../posts/02-minimal-rust-kernel/index.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md index 3dfed1a6..8d1421b1 100644 --- a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md +++ b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md @@ -343,7 +343,7 @@ Instead of writing our own bootloader, which is a project on its own, we use the # in Cargo.toml [dependencies] -bootloader = "0.4.0" +bootloader = "0.5.1" ``` Adding the bootloader as dependency is not enough to actually create a bootable disk image. The problem is that we need to combine the bootloader with the kernel after it has been compiled, but cargo has no support for additional build steps after successful compilation (see [this issue][post-build script] for more information). @@ -353,20 +353,22 @@ Adding the bootloader as dependency is not enough to actually create a bootable To solve this problem, we created a tool named `bootimage` that first compiles the kernel and bootloader, and then combines them to create a bootable disk image. To install the tool, execute the following command in your terminal: ``` -cargo install bootimage --version "^0.5.0" +cargo install bootimage --version "^0.7.1" ``` -The `^0.5.0` is a so-called [_caret requirement_], which means "version `0.5.0` or a later compatible version". So if we find a bug and publish version `0.5.1` or `0.5.2`, cargo would automatically use the latest version, as long as it is still a version `0.5.x`. However, it wouldn't choose version `0.6.0`, because it is not considered as compatible. Note that dependencies in your `Cargo.toml` are caret requirements by default, so the same rules are applied to our bootloader dependency. +The `^0.7.1` is a so-called [_caret requirement_], which means "version `0.7.1` or a later compatible version". So if we find a bug and publish version `0.7.2` or `0.7.3`, cargo would automatically use the latest version, as long as it is still a version `0.7.x`. However, it wouldn't choose version `0.8.0`, because it is not considered as compatible. Note that dependencies in your `Cargo.toml` are caret requirements by default, so the same rules are applied to our bootloader dependency. [_caret requirement_]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements -After installing the `bootimage` tool, creating a bootable disk image is as easy as executing: +For running `bootimage` and building the bootloader, you need to have the `llvm-tools-preview` rustup component installed. You can do so by executing `rustup component add llvm-tools-preview`. + +After installing `bootimage` and adding the `llvm-tools-preview` component, we can create a bootable disk image by executing: ``` > bootimage build --target x86_64-blog_os.json ``` -You see that the tool recompiles your kernel using `cargo xbuild`, so it will automatically pick up any changes you make. Afterwards it compiles the bootloader, which might take a while. Like all crate dependencies it is only built once and then cached, so subsequent builds will be much faster. Finally, `bootimage` combines the bootloader and your kernel to a bootable disk image. +We see that the tool recompiles our kernel using `cargo xbuild`, so it will automatically pick up any changes you make. Afterwards it compiles the bootloader, which might take a while. Like all crate dependencies it is only built once and then cached, so subsequent builds will be much faster. Finally, `bootimage` combines the bootloader and your kernel to a bootable disk image. After executing the command, you should see a bootable disk image named `bootimage-blog_os.bin` in your `target/x86_64-blog_os/debug` directory. You can boot it in a virtual machine or copy it to an USB drive to boot it on real hardware. (Note that this is not a CD image, which have a different format, so burning it to a CD doesn't work). From 6015feb5110102176796317c53096d5fbe92d4f0 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sat, 6 Apr 2019 17:49:31 +0200 Subject: [PATCH 2/2] Update 'Paging Implementation' post for bootloader 0.5.1 --- .../posts/10-paging-implementation/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/blog/content/second-edition/posts/10-paging-implementation/index.md b/blog/content/second-edition/posts/10-paging-implementation/index.md index 9ecbadcf..0c4b67bf 100644 --- a/blog/content/second-edition/posts/10-paging-implementation/index.md +++ b/blog/content/second-edition/posts/10-paging-implementation/index.md @@ -47,11 +47,11 @@ To implement the approach, we will need support from the bootloader, so we'll co ### Dependency Updates -This post requires version 0.4.0 or later of the `bootloader` dependency and version 0.5.2 or later of the `x86_64` dependency. You can update the dependencies in your `Cargo.toml`: +This post requires version 0.5.1 or later of the `bootloader` dependency and version 0.5.2 or later of the `x86_64` dependency. You can update the dependencies in your `Cargo.toml`: ```toml [dependencies] -bootloader = "0.4.0" +bootloader = "0.5.1" x86_64 = "0.5.2" ``` @@ -305,7 +305,7 @@ We choose the first approach for our kernel since it is simple, platform-indepen ```toml [dependencies] -bootloader = { version = "0.4.0", features = ["map_physical_memory"]} +bootloader = { version = "0.5.1", features = ["map_physical_memory"]} ``` With this feature enabled, the bootloader maps the complete physical memory to some unused virtual address range. To communicate the virtual address range to our kernel, the bootloader passes a _boot information_ structure. @@ -342,7 +342,7 @@ Since our `_start` function is called externally from the bootloader, no checkin To make sure that the entry point function has always the correct signature that the bootloader expects, the `bootloader` crate provides an [`entry_point`] macro that provides a type-checked way to define a Rust function as the entry point. Let's rewrite our entry point function to use this macro: -[`entry_point`]: https://docs.rs/bootloader/0.4.0/bootloader/macro.entry_point.html +[`entry_point`]: https://docs.rs/bootloader/0.5.1/bootloader/macro.entry_point.html ```rust // in src/main.rs @@ -889,7 +889,7 @@ This function uses iterator combinator methods to transform the initial `MemoryM - The third step is the most complicated: We convert each range to an iterator through the `into_iter` method and then choose every 4096th address using [`step_by`]. Since 4096 bytes (= 4 KiB) is the page size, we get the start address of each frame. The bootloader page aligns all usable memory areas so that we don't need any alignment or rounding code here. By using [`flat_map`] instead of `map`, we get an `Iterator` instead of an `Iterator>`. - In the final step, we convert the start addresses to `PhysFrame` types to construct the desired `Iterator`. We then use this iterator to create and return a new `BootInfoFrameAllocator`. -[`MemoryRegion`]: https://docs.rs/bootloader/0.4.0/bootloader/bootinfo/struct.MemoryRegion.html +[`MemoryRegion`]: https://docs.rs/bootloader/0.5.1/bootloader/bootinfo/struct.MemoryRegion.html [`filter`]: https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.filter [`map`]: https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.map [range syntax]: https://doc.rust-lang.org/core/ops/struct.Range.html