feat: misc

Nicer kernel, now can fetch multiboot2 boot info
This commit is contained in:
2026-02-21 22:12:23 +01:00
parent a2dfc5c775
commit e6b231488d
11 changed files with 282 additions and 27 deletions

View File

@@ -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
}
}
}
}