1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#![no_std]
pub use boot_loader_name::BootLoaderNameTag;
pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
pub use elf_sections::{ELF_SECTION_WRITABLE, ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE};
pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
pub use module::{ModuleTag};
#[macro_use]
extern crate bitflags;
mod boot_loader_name;
mod elf_sections;
mod memory_map;
mod module;
pub unsafe fn load(address: usize) -> &'static BootInformation {
let multiboot = &*(address as *const BootInformation);
assert!(multiboot.has_valid_end_tag());
multiboot
}
#[repr(C)]
pub struct BootInformation {
pub total_size: u32,
_reserved: u32,
first_tag: Tag,
}
impl BootInformation {
pub fn start_address(&self) -> usize {
self as *const _ as usize
}
pub fn end_address(&self) -> usize {
self.start_address() + self.total_size as usize
}
pub fn elf_sections_tag(&self) -> Option<&'static ElfSectionsTag> {
self.get_tag(9).map(|tag| unsafe{&*(tag as *const Tag as *const ElfSectionsTag)})
}
pub fn memory_map_tag(&self) -> Option<&'static MemoryMapTag> {
self.get_tag(6).map(|tag| unsafe{&*(tag as *const Tag as *const MemoryMapTag)})
}
pub fn module_tag(&self) -> Option<&'static ModuleTag> {
self.get_tag(3).map(|tag| unsafe{&*(tag as *const Tag as *const ModuleTag)})
}
pub fn boot_loader_name_tag(&self) -> Option<&'static BootLoaderNameTag> {
self.get_tag(2).map(|tag| unsafe{&*(tag as *const Tag as *const BootLoaderNameTag)})
}
fn has_valid_end_tag(&self) -> bool {
const END_TAG: Tag = Tag{typ:0, size:8};
let self_ptr = self as *const _;
let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
let end_tag = unsafe{&*(end_tag_addr as *const Tag)};
end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
}
fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
self.tags().find(|tag| tag.typ == typ)
}
fn tags(&self) -> TagIter {
TagIter{current: &self.first_tag as *const _}
}
}
#[repr(C)]
struct Tag {
typ: u32,
size: u32,
}
struct TagIter {
current: *const Tag,
}
impl Iterator for TagIter {
type Item = &'static Tag;
fn next(&mut self) -> Option<&'static Tag> {
match unsafe{&*self.current} {
&Tag{typ:0, size:8} => None,
tag => {
let mut tag_addr = self.current as usize;
tag_addr += tag.size as usize;
tag_addr = ((tag_addr-1) & !0x7) + 0x8;
self.current = tag_addr as *const _;
Some(tag)
},
}
}
}