Skip to content

Add BasicMemoryInfo and SMBIOS tags #137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions multiboot2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -76,6 +77,7 @@ mod image_load_addr;
mod memory_map;
mod module;
mod rsdp;
mod smbios;
mod tag_type;
mod vbe_info;

Expand Down Expand Up @@ -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::<BasicMemoryInfoTag, _>(TagType::BasicMeminfo)
}

/// Search for the ELF Sections tag.
pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
self.get_tag::<Tag, _>(TagType::ElfSections)
Expand Down Expand Up @@ -304,6 +311,11 @@ impl BootInformation {
self.get_tag::<VBEInfoTag, _>(TagType::Vbe)
}

/// Search for the SMBIOS tag.
pub fn smbios_tag(&self) -> Option<&SmbiosTag> {
self.get_tag::<SmbiosTag, _>(TagType::Smbios)
}

fn get(&self) -> &BootInformationInner {
unsafe { &*self.inner }
}
Expand Down
35 changes: 35 additions & 0 deletions multiboot2/src/memory_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
69 changes: 69 additions & 0 deletions multiboot2/src/smbios.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::{Tag, TagTrait, TagTypeId};

use core::fmt::Debug;

const METADATA_SIZE: usize = core::mem::size_of::<TagTypeId>()
+ core::mem::size_of::<u32>()
+ core::mem::size_of::<u8>() * 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<u8> {
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::<Tag>() };
let tag = tag.cast_tag::<SmbiosTag>();
assert_eq!({ tag.typ }, TagType::Smbios);
assert_eq!(tag.major, 3);
assert_eq!(tag.minor, 0);
assert_eq!(tag.tables, [0xabu8; 24]);
}
}