feat: misc
Nicer kernel, now can fetch multiboot2 boot info
This commit is contained in:
@@ -39,4 +39,175 @@ impl Default for Header {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum HeaderArchitecture {
|
||||
ProtectedI386 = 0,
|
||||
MIPS32 = 4,
|
||||
}
|
||||
|
||||
pub mod bif {
|
||||
//! # Boot Information Format
|
||||
//!
|
||||
//! <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html>
|
||||
|
||||
use core::ptr;
|
||||
|
||||
pub trait TagType {
|
||||
const ID: u32 = 4;
|
||||
}
|
||||
|
||||
pub mod types {
|
||||
macro tagset($taggedvis:vis $taggedname:ident { $( $typname:ident ($typn:expr) { $($typprop:ident : $typpropty:ty),* $(,)? } ),* $(,)? }) {
|
||||
$(
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct $typname { $(pub $typprop: $typpropty),* }
|
||||
|
||||
impl super::TagType for $typname {
|
||||
const ID: u32 = $typn;
|
||||
}
|
||||
)*
|
||||
|
||||
#[derive(Debug)]
|
||||
$taggedvis enum $taggedname<'a> {
|
||||
$( $typname(&'a $typname) ),*
|
||||
}
|
||||
}
|
||||
|
||||
tagset! { pub TagTagged {
|
||||
|
||||
Terminate(0) {},
|
||||
BootCommandLine(1) {
|
||||
string: [u8],
|
||||
},
|
||||
BootLoaderName(2) {
|
||||
string: [u8],
|
||||
},
|
||||
BasicMemoryInformation(4) {
|
||||
mem_lower: u32,
|
||||
mem_upper: u32,
|
||||
},
|
||||
BIOSBootDevice(5) {
|
||||
biosdev: u32,
|
||||
partition: u32,
|
||||
sub_partition: u32,
|
||||
},
|
||||
ImageLoadBasePhyAddr(21) {
|
||||
load_base_addr: u32,
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
pub use types::TagTagged;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TagHead {
|
||||
typ: u32,
|
||||
size: u32,
|
||||
__end: (),
|
||||
}
|
||||
|
||||
impl TagHead {
|
||||
pub fn typ(&self) -> u32 {
|
||||
self.typ
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u32 {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn aligned8_size(&self) -> u32 {
|
||||
(self.size + 7) & !7
|
||||
}
|
||||
|
||||
/// Gets the reference of the next laying in memory tag, considering this one's size.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Assumes there's a contiguous one in memory.
|
||||
pub unsafe fn next(&self) -> &Self {
|
||||
unsafe { &*ptr::from_ref(self).byte_add(self.aligned8_size() as usize) }
|
||||
}
|
||||
|
||||
pub fn tag<'a>(&self) -> Option<TagTagged<'a>> {
|
||||
let typ = self.typ;
|
||||
let size = self.size;
|
||||
|
||||
let contents_addr = ptr::addr_of!(self.__end).cast::<()>();
|
||||
|
||||
macro typ_match(match $var:ident { $($name:ident)* } fat { $($fatname:ident)* }) {
|
||||
match $var {
|
||||
$(
|
||||
types::$name::ID => Some(TagTagged::$name(unsafe {
|
||||
&*core::ptr::from_raw_parts::<types::$name>(
|
||||
contents_addr,
|
||||
(),
|
||||
)
|
||||
}))
|
||||
),*,
|
||||
$(
|
||||
types::$fatname::ID => Some(TagTagged::$fatname(unsafe {
|
||||
&*core::ptr::from_raw_parts::<types::$fatname>(
|
||||
contents_addr,
|
||||
size as usize - core::mem::size_of::<Self>(),
|
||||
)
|
||||
}))
|
||||
),*,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
typ_match!(match typ {
|
||||
BasicMemoryInformation
|
||||
BIOSBootDevice
|
||||
Terminate
|
||||
ImageLoadBasePhyAddr
|
||||
} fat {
|
||||
BootCommandLine
|
||||
BootLoaderName
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
/// Represents the fixed part of the BIF
|
||||
#[repr(C, align(8))]
|
||||
pub struct FixedPart {
|
||||
pub total_size: u32,
|
||||
_reserved: u32,
|
||||
__end: (),
|
||||
}
|
||||
|
||||
/// Iterator for the tags of a [`FixedPart`]
|
||||
pub struct TagsIter<'a> {
|
||||
rem_size: u32,
|
||||
next_ref: &'a TagHead,
|
||||
}
|
||||
|
||||
impl<'a> TagsIter<'a> {
|
||||
pub fn new(fixed: &FixedPart) -> Self {
|
||||
let rem_size = fixed.total_size - core::mem::size_of::<FixedPart>() as u32;
|
||||
let next_ptr = unsafe { &*core::ptr::addr_of!(fixed.__end).cast() };
|
||||
|
||||
Self {
|
||||
rem_size,
|
||||
next_ref: next_ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TagsIter<'a> {
|
||||
type Item = &'a TagHead;
|
||||
|
||||
fn next(&mut self) -> Option<&'a TagHead> {
|
||||
if self.rem_size > 0 {
|
||||
let this_ref = self.next_ref;
|
||||
self.rem_size -= this_ref.aligned8_size();
|
||||
// SAFETY: if there were no tags left we'd reach rem_size and not use this referece
|
||||
// any further
|
||||
self.next_ref = unsafe { this_ref.next() };
|
||||
Some(this_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user