diff --git a/multiboot2/src/lib.rs b/multiboot2/src/lib.rs index ef0ce6a9..b81f787c 100644 --- a/multiboot2/src/lib.rs +++ b/multiboot2/src/lib.rs @@ -52,11 +52,12 @@ pub use elf_sections::{ pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, FramebufferType}; pub use image_load_addr::ImageLoadPhysAddr; pub use memory_map::{ - EFIMemoryAreaType, EFIMemoryDesc, EFIMemoryMapTag, MemoryArea, MemoryAreaIter, MemoryAreaType, - MemoryMapTag, + BasicMemoryInfoTag, EFIMemoryAreaType, EFIMemoryDesc, EFIMemoryMapTag, MemoryArea, + MemoryAreaIter, MemoryAreaType, MemoryMapTag, }; pub use module::{ModuleIter, ModuleTag}; pub use rsdp::{RsdpV1Tag, RsdpV2Tag}; +pub use smbios::SmbiosTag; use tag_type::TagIter; pub use tag_type::{Tag, TagType, TagTypeId}; pub use vbe_info::{ @@ -76,6 +77,7 @@ mod image_load_addr; mod memory_map; mod module; mod rsdp; +mod smbios; mod tag_type; mod vbe_info; @@ -218,6 +220,11 @@ impl BootInformation { self.get().total_size as usize } + /// Search for the basic memory info tag. + pub fn basic_memory_info_tag(&self) -> Option<&BasicMemoryInfoTag> { + self.get_tag::(TagType::BasicMeminfo) + } + /// Search for the ELF Sections tag. pub fn elf_sections_tag(&self) -> Option { self.get_tag::(TagType::ElfSections) @@ -304,6 +311,11 @@ impl BootInformation { self.get_tag::(TagType::Vbe) } + /// Search for the SMBIOS tag. + pub fn smbios_tag(&self) -> Option<&SmbiosTag> { + self.get_tag::(TagType::Smbios) + } + fn get(&self) -> &BootInformationInner { unsafe { &*self.inner } } diff --git a/multiboot2/src/memory_map.rs b/multiboot2/src/memory_map.rs index e60cdec0..36c7203e 100644 --- a/multiboot2/src/memory_map.rs +++ b/multiboot2/src/memory_map.rs @@ -123,6 +123,41 @@ impl<'a> Iterator for MemoryAreaIter<'a> { } } +/// Basic memory info +/// +/// This tag includes "basic memory information". +/// This means (legacy) lower and upper memory: +/// In Real Mode (modeled after the 8086), +/// only the first 1MB of memory is accessible. +/// Typically, the region between 640KB and 1MB is not freely usable, +/// because it is used for memory-mapped IO, for instance. +/// The term “lower memory” refers to those first 640KB of memory that are +/// freely usable for an application in Real Mode. +/// “Upper memory” then refers to the next freely usable chunk of memory, +/// starting at 1MB up to about 10MB, in practice. +/// This is the memory an application running on a 286 +/// (which had a 24-bit address bus) could use, historically. +/// Nowadays, much bigger chunks of continuous memory are available at higher +/// addresses, but the Multiboot standard still references those two terms. +#[derive(Debug)] +#[repr(C, packed)] +pub struct BasicMemoryInfoTag { + typ: TagTypeId, + size: u32, + memory_lower: u32, + memory_upper: u32, +} + +impl BasicMemoryInfoTag { + pub fn memory_lower(&self) -> u32 { + self.memory_lower + } + + pub fn memory_upper(&self) -> u32 { + self.memory_upper + } +} + /// EFI memory map as per EFI specification. #[derive(Debug)] #[repr(C)] diff --git a/multiboot2/src/smbios.rs b/multiboot2/src/smbios.rs new file mode 100644 index 00000000..12a4ec60 --- /dev/null +++ b/multiboot2/src/smbios.rs @@ -0,0 +1,69 @@ +use crate::{Tag, TagTrait, TagTypeId}; + +use core::fmt::Debug; + +const METADATA_SIZE: usize = core::mem::size_of::() + + core::mem::size_of::() + + core::mem::size_of::() * 8; + +/// This tag contains a copy of SMBIOS tables as well as their version. +#[derive(ptr_meta::Pointee)] +#[repr(C, packed)] +pub struct SmbiosTag { + typ: TagTypeId, + size: u32, + pub major: u8, + pub minor: u8, + _reserved: [u8; 6], + pub tables: [u8], +} + +impl TagTrait for SmbiosTag { + fn dst_size(base_tag: &Tag) -> usize { + assert!(base_tag.size as usize >= METADATA_SIZE); + base_tag.size as usize - METADATA_SIZE + } +} + +impl Debug for SmbiosTag { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("BootLoaderNameTag") + .field("typ", &{ self.typ }) + .field("size", &{ self.size }) + .field("major", &{ self.major }) + .field("minor", &{ self.minor }) + .finish() + } +} + +#[cfg(test)] +mod tests { + use crate::{SmbiosTag, Tag, TagType}; + + /// Returns the tag structure in bytes in native endian format. + fn get_bytes() -> std::vec::Vec { + let tables = [0xabu8; 24]; + // size is: 4 bytes for tag + 4 bytes for size + 1 byte for major and minor + // + 6 bytes reserved + the actual tables + let size = (4 + 4 + 1 + 1 + 6 + tables.len()) as u32; + let typ: u32 = TagType::Smbios.into(); + let mut bytes = [typ.to_ne_bytes(), size.to_ne_bytes()].concat(); + bytes.push(3); + bytes.push(0); + bytes.extend([0; 6]); + bytes.extend(tables); + bytes + } + + /// Test to parse a given tag. + #[test] + fn test_parse() { + let tag = get_bytes(); + let tag = unsafe { &*tag.as_ptr().cast::() }; + let tag = tag.cast_tag::(); + assert_eq!({ tag.typ }, TagType::Smbios); + assert_eq!(tag.major, 3); + assert_eq!(tag.minor, 0); + assert_eq!(tag.tables, [0xabu8; 24]); + } +}