mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Convert links to hugo format and insert more breaks
This commit is contained in:
@@ -9,9 +9,12 @@ aliases = [
|
||||
|
||||
This post explains how to create a minimal x86 operating system kernel. In fact, it will just boot and print `OK` to the screen. The following blog posts we will extend it using the [Rust] programming language.
|
||||
|
||||
[Rust]: http://www.rust-lang.org/
|
||||
|
||||
<!--more-->
|
||||
|
||||
I tried to explain everything in detail and to keep the code as simple as possible. If you have any questions, suggestions or other issues, please leave a comment or [create an issue] on Github. The source code is available in a [repository][source code], too.
|
||||
|
||||
[Rust]: http://www.rust-lang.org/
|
||||
[create an issue]: https://github.com/phil-opp/blog_os/issues
|
||||
[source code]: https://github.com/phil-opp/blog_os/tree/multiboot_bootstrap/src/arch/x86_64
|
||||
|
||||
@@ -187,7 +190,7 @@ Idx Name Size VMA LMA File off Algn
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
```
|
||||
_Note_: The `ld` and `objdump` commands are platform specific. If you're _not_ working on x86_64 architecture, you will need to [cross compile binutils]. Then use `x86_64‑elf‑ld` and `x86_64‑elf‑objdump` instead of `ld` and `objdump`.
|
||||
[cross compile binutils]: /cross-compile-binutils.html
|
||||
[cross compile binutils]: {{% relref "cross-compile-binutils.md" %}}
|
||||
|
||||
## Creating the ISO
|
||||
The last step is to create a bootable ISO image with GRUB. We need to create the following directory structure and copy the `kernel.bin` to the right place:
|
||||
@@ -317,5 +320,5 @@ Now we can invoke `make` and all updated assembly files are compiled and linked.
|
||||
|
||||
In the [next post] we will create a page table and do some CPU configuration to switch to the 64-bit [long mode].
|
||||
|
||||
[next post]: {{ page.next.url }}
|
||||
[next post]: {{% relref "2015-08-25-entering-longmode.md" %}}
|
||||
[long mode]: https://en.wikipedia.org/wiki/Long_mode
|
||||
|
||||
@@ -10,12 +10,15 @@ aliases = [
|
||||
|
||||
In the [previous post] we created a minimal multiboot kernel. It just prints `OK` and hangs. The goal is to extend it and call 64-bit [Rust] code. But the CPU is currently in [protected mode] and allows only 32-bit instructions and up to 4GiB memory. So we need to set up _Paging_ and switch to the 64-bit [long mode] first.
|
||||
|
||||
I tried to explain everything in detail and to keep the code as simple as possible. If you have any questions, suggestions, or issues, please leave a comment or [create an issue] on Github. The source code is available in a [repository][source code], too.
|
||||
|
||||
[previous post]: {{ page.previous.url }}
|
||||
[previous post]: {{% relref "2015-08-18-multiboot-kernel.md" %}}
|
||||
[Rust]: http://www.rust-lang.org/
|
||||
[protected mode]: https://en.wikipedia.org/wiki/Protected_mode
|
||||
[long mode]: https://en.wikipedia.org/wiki/Long_mode
|
||||
|
||||
<!--more-->
|
||||
|
||||
I tried to explain everything in detail and to keep the code as simple as possible. If you have any questions, suggestions, or issues, please leave a comment or [create an issue] on Github. The source code is available in a [repository][source code], too.
|
||||
|
||||
[create an issue]: https://github.com/phil-opp/blog_os/issues
|
||||
[source code]: https://github.com/phil-opp/blog_os/tree/entering_longmode/src/arch/x86_64
|
||||
|
||||
@@ -38,7 +41,7 @@ error:
|
||||
At address `0xb8000` begins the so-called [VGA text buffer]. It's an array of screen characters that are displayed by the graphics card. A [future post] will cover the VGA buffer in detail and create a Rust interface to it. But for now, manual bit-fiddling is the easiest option.
|
||||
|
||||
[VGA text buffer]: https://en.wikipedia.org/wiki/VGA-compatible_text_mode
|
||||
[future post]: {{ page.next.next.url }}
|
||||
[future post]: {{% relref "2015-10-23-printing-to-screen.md" %}}
|
||||
|
||||
A screen character consists of a 8 bit color code and a 8 bit [ASCII] character. We used the color code `4f` for all characters, which means white text on red background. `0x52` is an ASCII `R`, `0x45` is an `E`, `0x3a` is a `:`, and `0x20` is a space. The second space is overwritten by the given ASCII byte. Finally the CPU is stopped with the `hlt` instruction.
|
||||
|
||||
@@ -530,4 +533,4 @@ It's time to finally leave assembly behind[^leave_assembly_behind] and switch to
|
||||
[^leave_assembly_behind]: Actually we will still need some assembly in the future, but I'll try to minimize it.
|
||||
|
||||
[Rust]: https://www.rust-lang.org/
|
||||
[next post]: {{ page.next.url }}
|
||||
[next post]: {{% relref "2015-09-02-set-up-rust.md" %}}
|
||||
|
||||
@@ -9,11 +9,14 @@ aliases = [
|
||||
|
||||
In the previous posts we created a [minimal Multiboot kernel][multiboot post] and [switched to Long Mode][long mode post]. Now we can finally switch to [Rust] code. Rust is a high-level language without runtime. It allows us to not link the standard library and write bare metal code. Unfortunately the setup is not quite hassle-free yet.
|
||||
|
||||
[multiboot post]: {{% relref "2015-08-18-multiboot-kernel.md" %}}
|
||||
[long mode post]: {{% relref "2015-08-25-entering-longmode.md" %}}
|
||||
[Rust]: https://www.rust-lang.org/
|
||||
|
||||
<!--more-->
|
||||
|
||||
This blog post tries to set up Rust step-by-step and point out the different problems. If you have any questions, problems, or suggestions please [file an issue] or create a comment at the bottom. The code from this post is in a [Github repository], too.
|
||||
|
||||
[multiboot post]: {{ page.previous.previous.url }}
|
||||
[long mode post]: {{ page.previous.url }}
|
||||
[Rust]: https://www.rust-lang.org/
|
||||
[file an issue]: https://github.com/phil-opp/blog_os/issues
|
||||
[Github repository]: https://github.com/phil-opp/blog_os/tree/set_up_rust
|
||||
|
||||
@@ -79,7 +82,7 @@ We can now build it using `cargo build`. To make sure, we are building it for th
|
||||
cargo build --target=x86_64-unknown-linux-gnu
|
||||
```
|
||||
It creates a static library at `target/x86_64-unknown-linux-gnu/debug/libblog_os.a`, which can be linked with our assembly kernel. If you're getting an error about a missing `core` crate, [look here][cross compile libcore].
|
||||
[cross compile libcore]: /cross-compile-libcore.html
|
||||
[cross compile libcore]: {{% relref "cross-compile-libcore.md" %}}
|
||||
|
||||
To build and link the rust library on `make`, we extend our `Makefile`([full file][github makefile]):
|
||||
|
||||
@@ -368,10 +371,10 @@ Some notes:
|
||||
### Stack Overflows
|
||||
Since we still use the small 64 byte [stack from the last post], we must be careful not to [overflow] it. Normally, Rust tries to avoid stack overflows through _guard pages_: The page below the stack isn't mapped and such a stack overflow triggers a page fault (instead of silently overwriting random memory). But we can't unmap the page below our stack right now since we currently use only a single big page. Fortunately the stack is located just above the page tables. So some important page table entry would probably get overwritten on stack overflow and then a page fault occurs, too.
|
||||
|
||||
[stack from the last post]: {{ page.previous.url }}#creating-a-stack
|
||||
[stack from the last post]: {{% relref "2015-08-25-entering-longmode.md#creating-a-stack" %}}
|
||||
[overflow]: https://en.wikipedia.org/wiki/Stack_overflow
|
||||
|
||||
## What's next?
|
||||
Until now we write magic bits to some memory location when we want to print something to screen. In the [next post] we create a abstraction for the VGA text buffer that allows us to print strings in different colors and provides a simple interface.
|
||||
|
||||
[next post]: {{ page.next.url }}
|
||||
[next post]: {{% relref "2015-10-23-printing-to-screen.md" %}}
|
||||
|
||||
@@ -8,11 +8,13 @@ aliases = [
|
||||
|
||||
In the [previous post] we switched from assembly to [Rust], a systems programming language that provides great safety. But so far we are using unsafe features like [raw pointers] whenever we want to print to screen. In this post we will create a Rust module that provides a safe and easy-to-use interface for the VGA text buffer. It will support Rust's [formatting macros], too.
|
||||
|
||||
[previous post]: {{ page.previous.url }}
|
||||
[previous post]: {{% relref "2015-09-02-set-up-rust.md" %}}
|
||||
[Rust]: https://www.rust-lang.org/
|
||||
[raw pointers]: https://doc.rust-lang.org/book/raw-pointers.html
|
||||
[formatting macros]: https://doc.rust-lang.org/std/fmt/#related-macros
|
||||
|
||||
<!--more-->
|
||||
|
||||
This post uses recent unstable features, so you need an up-to-date nighly compiler. If you have any questions, problems, or suggestions please [file an issue] or create a comment at the bottom. The code from this post is also available on [Github][code repository].
|
||||
|
||||
[file an issue]: https://github.com/phil-opp/blog_os/issues
|
||||
@@ -452,7 +454,7 @@ In the next posts we will map the kernel pages correctly so that accessing `0x0`
|
||||
|
||||
The [next post] describes the Multiboot information structure and creates a frame allocator using the information about memory areas.
|
||||
|
||||
[next post]: {{ page.next.url }}
|
||||
[next post]: {{% relref "2015-11-15-allocating-frames.md" %}}
|
||||
|
||||
## Other Rust OS Projects
|
||||
Now that you know the very basics of OS development in Rust, you should also check out the following projects:
|
||||
@@ -461,7 +463,7 @@ Now that you know the very basics of OS development in Rust, you should also che
|
||||
_Note_: You need to [cross compile binutils] to build it (or you create some symbolic links[^fn-symlink] if you're on x86_64).
|
||||
[Rust Bare-Bones Kernel]: https://github.com/thepowersgang/rust-barebones-kernel
|
||||
[higher half]: http://wiki.osdev.org/Higher_Half_Kernel
|
||||
[cross compile binutils]: /cross-compile-binutils.html
|
||||
[cross compile binutils]: {{% relref "cross-compile-binutils.md" %}}
|
||||
[^fn-symlink]: You will need to symlink `x86_64-none_elf-XXX` to `/usr/bin/XXX` where `XXX` is in {`as`, `ld`, `objcopy`, `objdump`, `strip`}. The `x86_64-none_elf-XXX` files must be in some folder that is in your `$PATH`. But then you can only build for your x86_64 host architecture, so use this hack only for testing.
|
||||
|
||||
- [RustOS]: More advanced kernel that supports allocation, keyboard inputs, and threads. It also has a scheduler and a basic network driver.
|
||||
|
||||
@@ -5,6 +5,8 @@ date = "2015-11-15"
|
||||
|
||||
In this post we create an allocator that provides free physical frames for a future paging module. To get the required information about available and used memory we use the Multiboot information structure. Additionally, we improve the `panic` handler to print the corresponding message and source line.
|
||||
|
||||
<!--more-->
|
||||
|
||||
The full source code is available on [Github][source repo]. Feel free to open issues there if you have any problems or improvements. You can also leave a comment at the bottom.
|
||||
|
||||
[source repo]: https://github.com/phil-opp/blog_os/tree/allocating_frames
|
||||
@@ -392,10 +394,10 @@ Now we have a working frame allocator. It is a bit rudimentary and cannot free f
|
||||
## What's next?
|
||||
The [next post] will be about paging again. We will use the frame allocator to create a safe module that allows us to switch page tables and map pages. Then we will use this module and the information from the Elf-sections tag to remap the kernel correctly.
|
||||
|
||||
[next post]: {{ page.next.url }}
|
||||
[next post]: {{% relref "2015-12-09-modifying-page-tables.md" %}}
|
||||
|
||||
## Recommended Posts
|
||||
Eric Kidd started the [Bare Metal Rust] series last week. Like this post, it builds upon the code from [Printing to Screen], but tries to support keyboard input instead of wrestling through memory management details ;).
|
||||
|
||||
[Bare Metal Rust]: http://www.randomhacks.net/bare-metal-rust/
|
||||
[Printing to Screen]: {% post_url 2015-10-23-printing-to-screen %}
|
||||
[Printing to Screen]: {{% relref "2015-10-23-printing-to-screen.md" %}}
|
||||
|
||||
@@ -6,6 +6,8 @@ date = "2015-12-09"
|
||||
|
||||
In this post we will create a paging module, which allows us to access and modify the 4-level page table. We will explore recursive page table mapping and use some Rust features to make it safe. Finally we will create functions to translate virtual addresses and to map and unmap pages.
|
||||
|
||||
<!--more-->
|
||||
|
||||
You can find the source code and this post itself on [Github][source repository]. Please file an issue there if you have any problems or improvement suggestions. There is also a comment section at the end of this page. Note that this post requires a current Rust nightly.
|
||||
|
||||
[source repository]: https://github.com/phil-opp/blog_os/tree/page_tables
|
||||
@@ -47,7 +49,7 @@ pub struct Page {
|
||||
```
|
||||
We import the `PAGE_SIZE` and define a constant for the number of entries per table. To make future function signatures more expressive, we can use the type aliases `PhysicalAddress` and `VirtualAddress`. The `Page` struct is similar to the `Frame` struct in the [previous post], but represents a virtual page instead of a physical frame.
|
||||
|
||||
[previous post]: {{ page.previous.url }}#a-memory-module
|
||||
[previous post]: {{% relref "2015-11-15-allocating-frames.md#a-memory-module" %}}
|
||||
|
||||
### Page Table Entries
|
||||
To model page table entries, we create a new `entry` submodule:
|
||||
@@ -636,7 +638,7 @@ pub struct ActivePageTable {
|
||||
```
|
||||
We can't store the `Table<Level4>` directly because it needs to be at a special memory location (like the [VGA text buffer]). We could use a raw pointer or `&mut` instead of [Unique], but Unique indicates ownership better.
|
||||
|
||||
[VGA text buffer]: http://os.phil-opp.com/printing-to-screen.html#the-text-buffer
|
||||
[VGA text buffer]: {{% relref "2015-10-23-printing-to-screen.md#the-text-buffer" %}}
|
||||
[Unique]: https://doc.rust-lang.org/nightly/core/ptr/struct.Unique.html
|
||||
|
||||
Because the `ActivePageTable` owns the unique recursive mapped P4 table, there must be only one `ActivePageTable` instance. Thus we make the constructor function unsafe:
|
||||
@@ -921,7 +923,9 @@ This post has become pretty long. So let's summarize what we've done:
|
||||
- and we fixed stack overflow and TLB related bugs
|
||||
|
||||
## What's next?
|
||||
In the next post we will extend this module and add a function to modify inactive page tables. Through that function, we will create a new page table hierarchy that maps the kernel correctly using 4KiB pages. Then we will switch to the new table to get a safer kernel environment.
|
||||
In the [next post] we will extend this module and add a function to modify inactive page tables. Through that function, we will create a new page table hierarchy that maps the kernel correctly using 4KiB pages. Then we will switch to the new table to get a safer kernel environment.
|
||||
|
||||
[next post]: {{% relref "2016-01-01-remap-the-kernel.md" %}}
|
||||
|
||||
Afterwards, we will use this paging module to build a heap allocator. This will allow us to use allocation and collection types such as `Box` and `Vec`.
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ date = "2016-04-11"
|
||||
|
||||
In the previous posts we have created a [frame allocator] and a [page table module]. Now we are ready to create a kernel heap and a memory allocator. Thus, we will unlock `Box`, `Vec`, `BTreeMap`, and the rest of the [alloc] and [collections] crates.
|
||||
|
||||
[frame allocator]: {% post_url 2015-11-15-allocating-frames %}
|
||||
[page table module]: {% post_url 2015-12-09-modifying-page-tables %}
|
||||
[frame allocator]: {{% relref "2015-11-15-allocating-frames.md" %}}
|
||||
[page table module]: {{% relref "2015-12-09-modifying-page-tables.md" %}}
|
||||
[alloc]: https://doc.rust-lang.org/nightly/alloc/index.html
|
||||
[collections]: https://doc.rust-lang.org/nightly/collections/index.html
|
||||
|
||||
<!--more-->
|
||||
|
||||
As always, you can find the complete source code on [Github]. Please file [issues] for any problems, questions, or improvement suggestions. There is also a comment section at the end of this page.
|
||||
|
||||
[Github]: https://github.com/phil-opp/blog_os/tree/kernel_heap
|
||||
|
||||
Reference in New Issue
Block a user