rustubs/machine/
multiboot.rs1use crate::black_magic::flush;
5use crate::defs::{mb_info_pm_addr, mb_magic};
6use crate::P2V;
7use core::fmt;
8use core::ops::Range;
9use lazy_static::lazy_static;
10lazy_static! {
11 pub static ref MBOOTINFO: &'static MultibootInfo = unsafe {
21 &*(P2V(flush(&mb_info_pm_addr)).unwrap() as *const MultibootInfo)
22 };
23}
24
25pub fn get_mb_info() -> Option<&'static MultibootInfo> {
26 if !check() {
27 return None;
28 }
29 return Some(&MBOOTINFO);
30}
31
32pub fn check() -> bool {
35 if flush(&mb_magic) != 0x2BADB002 {
36 return false;
37 };
38 if P2V(flush(&mb_info_pm_addr)).is_none() {
39 return false;
40 }
41 let f = MBOOTINFO.get_flags();
43 return f.check_valid();
44}
45
46#[repr(C)]
47#[repr(packed)]
48pub struct MultibootMmap {
50 pub size: u32,
51 pub addr: u64,
52 pub len: u64,
53 pub mtype: u32,
54}
55
56impl MultibootMmap {
58 pub const MTYPE_RAM: u32 = 1;
60 pub const MTYPE_RAM_RES: u32 = 2;
62 pub const MTYPE_ACPI: u32 = 3;
64 pub const MTYPE_RAM_NVS: u32 = 4;
66 pub const MTYPE_RAM_DEFECT: u32 = 5;
68 pub fn get_range(&self) -> Range<u64> {
69 Range {
70 start: self.addr,
71 end: self.addr + self.len,
72 }
73 }
74 pub fn get_end(&self) -> u64 { return self.addr + self.len; }
75}
76
77#[repr(C)]
78#[repr(packed)]
79#[derive(Debug, Clone, Copy)]
80pub struct MultibootInfoMmap {
83 pub mmap_length: u32,
84 pub mmap_addr: u32,
85}
86
87pub fn _test_mmap() {
90 let mmapinfo = unsafe { MBOOTINFO.get_mmap() }.unwrap();
91 let buf_start = mmapinfo.mmap_addr;
92 let buf_len = mmapinfo.mmap_length;
93 let buf_end = buf_start + buf_len;
94 let mut curr = buf_start as u64;
95 loop {
96 if curr >= buf_end as u64 {
97 break;
98 }
99 let mblock = unsafe { &*(curr as *const MultibootMmap) };
100 curr += mblock.size as u64;
101 curr += 4; println!("mem block {:#X?}", mblock);
103 }
104}
105
106#[repr(C)]
107#[repr(packed)]
108#[derive(Debug, Clone, Copy)]
109pub struct MultibootInfoMem {
114 pub mem_lower: u32,
115 pub mem_upper: u32,
116}
117
118impl MultibootInfoMem {
122 pub fn lower(&self) -> u32 { self.mem_lower }
123 pub fn upper(&self) -> u32 { self.mem_upper }
124}
125
126#[repr(C)]
127#[repr(packed)]
128#[derive(Debug)]
129pub struct MultibootInfo {
134 flags: MultibootInfoFlags,
135 mem: MultibootInfoMem,
136 _pad1: [u8; 32],
137 mmap: MultibootInfoMmap,
138 _pad2: [u8; 68],
139}
140
141impl MultibootInfo {
143 fn get_flags(&self) -> MultibootInfoFlags { return self.flags; }
145
146 pub unsafe fn get_mem(&self) -> Option<MultibootInfoMem> {
147 if self.get_flags().contains(MultibootInfoFlags::MEM) {
148 return Some(self.mem);
149 } else {
150 return None;
151 }
152 }
153
154 pub unsafe fn get_mmap(&self) -> Option<MultibootInfoMmap> {
155 if self.get_flags().contains(MultibootInfoFlags::MMAP) {
156 return Some(self.mmap);
157 } else {
158 return None;
159 }
160 }
161}
162
163use bitflags::bitflags;
164bitflags! {
165 #[derive(Copy, Clone, Debug)]
168 pub struct MultibootInfoFlags: u32 {
169 const MEM = 1 << 0;
170 const BOOT_DEVICE = 1 << 1;
171 const CMDLINE = 1 << 2;
172 const MODS = 1 << 3;
173 const SYM_TBL = 1 << 4;
174 const SHDR = 1 << 5;
175 const MMAP = 1 << 6;
176 const DRIVES = 1 << 7;
177 const CONF_TBL = 1 << 8;
178 const BL_NAME = 1 << 9;
179 const APM_TBL = 1 << 10;
180 const VBE_TBL = 1 << 11;
181 const FRAMEBUFFER = 1 << 12;
182 }
183}
184
185impl MultibootInfoFlags {
186 const VALID_MASK: u32 = 0x1FFF;
189
190 pub fn check_valid(&self) -> bool {
191 return self.bits() <= Self::VALID_MASK;
192 }
193}
194
195impl fmt::Debug for MultibootMmap {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 let addr = self.addr;
198 let len = self.len;
199 let mtype = self.mtype;
200 write!(
201 f,
202 "[{}] @ {:#X} + {:#X}",
203 match mtype {
204 MultibootMmap::MTYPE_RAM => "GOOD",
205 MultibootMmap::MTYPE_RAM_RES => "RESV",
206 MultibootMmap::MTYPE_ACPI => "ACPI",
207 MultibootMmap::MTYPE_RAM_NVS => "NVS ",
208 MultibootMmap::MTYPE_RAM_DEFECT => "BAD ",
209 _ => "UNKN",
210 },
211 addr,
212 len,
213 )
214 }
215}