{% raw %}
Philipp Oppermann

There is some interesting discussion on reddit.

Tobias Schottdorf

> Note that we need to clone the iterator because the order of areas in the memory map isn't specified.

Could you elaborate on that? I'm probably getting something wrong, but I can't reproduce issues omitting the clone:

https://gist.github.com/tschottdorf/e1e0a4091136dd281ab3

Philipp Oppermann

The `clone` is required because the min_by function consumes the iterator. I updated that sentence. My initial reasoning was that we can't just use the next area in the iterator because Multiboot doesn't specify an increasing ordering. Thus we need to use `min_by` and clone the iterator.

Vikas Reddy

Later you are identity mapping the VGA buffer address..but in the frame allocator allocate_frame() function you are not pointing that out...may be some time later when you allocate more frames...it may be allocated to some other page...

Philipp Oppermann

Good catch! Fortunately it is part of the memory hole below the 1MiB mark. Thus it is never allocated by the frame allocator.

Errma Gerrd

if let Some(area) = self.current_area {

produces a `if let` arms have incompatible types [E0308] for me. (expected type `_` found type `()`.

is this due to my rust version (rustc 1.11.0-nightly (0554abac6 2016-06-10)? :o

EDIT:

i found my error!
// `frame` was not valid, try it again with the updated `next_free_frame`
self.allocate_frame();

should be ->

// `frame` was not valid, try it again with the updated `next_free_frame`
return self.allocate_frame();

in my own code of course :)

Gerald King

You can write simply `self.allocate_frame()` without `return`, but also without trailing semicolon (it's important). In Rust, it is considered better practice than using `return` as the last statement.

Errma Gerrd

yes... that semicolon killed me :D

I think I'll stick with `return expression;` because it looks alot more explicit :o
but thanks for the clue anyway! :)

Gerald King

Not at all :) I'm a Rust newbie too, and that syntax seems a bit unfamiliar for C++, Java, Python etc. programmers. (But Ruby has such a feature.)

Errma Gerrd

I use CoffeeScript at work which has this feature too. But I merely use it
using return IMHO has the advantage that it gets syntax highlighted in another color and you can scan easier for function return points :)

Gerald King

You are probably right about this :)

Gabriel Eiseman

These articles of yours are very good: I'm following them in C because they are better than any C tutorial I have yet found. However, I ran into a small problem with this one. In your Multiboot crate you define the ELF symbols tag as having 3 32 bit integers where the multiboot specification pdf you link to specifies 4 16 bit integers. The layout in your crate seems to be correct though, because I defined a struct in C (using __attribute__((packed))) according to the pdf and it did not work, but when I mirrored your layout it did.

Philipp Oppermann

Thanks for the nice words :). Honestly, I'm not quite sure about this. It's been a while since I wrote this code…

The multiboot specification (PDF) says:

This tag contains section header table from an ELF kernel, the size of each entry, number of entries, and the string table used as the index of names. They correspond to the ‘shdr_*’ entries (‘shdr_num’, etc.) in the Executable and Linkable Format (elf) specification in the program header.

So the `shdr_` entries are just the entries of the ELF header. The problem is that the multiboot specification uses 32-bit elf files implicitly, but our kernel is a 64-bit elf. There seem to be some format differences… However, the ELF64 specification (PDF) uses u16s too…

In the Readme of the multiboot2 crate I wrote:

Note that this format differs from the description in the Multiboot specification because if seems to be wrong for ELF 64 kernels: The number of entries, entry size, and string table fields seem to be u32 instead of u16 (but I'm not sure on this).

So I wasn't even sure on this when I wrote it :D.

I did some digging in the GRUB2 source and found the definition of `multiboot_tag_elf_sections`. Like the multiboot2 crate, it uses 3 u32s. So it seems like the crate is correct.

Redrield

When I get to the part when we're getting the kernel start and end, I'm getting a triple fault and the OS is stuck in a bootloop. This is my Bochs log https://gist.github.com/Red...

Philipp Oppermann

Hmm, I don't use Bochs, but according to this page of the Bochs user manual it seems to be a “no atapi cdrom found“ error. I have no idea why it occurs though… Does it work in QEMU?

Johan Montelius

Could we not use the start_address() and end_address() that are available in the BootInformation instead of doing the address calculation ourselves?

let multiboot_start = boot_info.start_address();

let multiboot_end = boot_info.end_address();

Philipp Oppermann

Sure! I think they were introduced after this post was written and I forgot to update this post.

Madeleine Berner

Hi! Your link for "re-export" under the section "Testing it" is broken.

Are you supposed to do something with the instruction "In order to test it in main, we need to re-export the AreaFrameAllocator in the memorymodule." ? I keep getting this error: "Could not find AreaFrameAllocator in memory "

in src/lib.rs on this row:

let mut frame_allocator = memory::AreaFrameAllocator::new(...

Madeleine Berner

Hi (again)! I just found the code to add to fix my problem. Perhaps you can add it to your blog post?

From this commit I added the new lines from the file mod.rs:

https://github.com/phil-opp/blog_os/commit/9f1a69cafa8a1b09dd71cbf3bf7493e388576391#diff-8c6f6418d9ea96c33ce93b05462bfd65

{% endraw %}