Browse Source

Merge pull request #137 from YtvwlD/bootloader-tags

Add BasicMemoryInfo and SMBIOS tags
Philipp Schuster 1 year ago
parent
commit
798e0819c8
3 changed files with 118 additions and 2 deletions
  1. 14 2
      multiboot2/src/lib.rs
  2. 35 0
      multiboot2/src/memory_map.rs
  3. 69 0
      multiboot2/src/smbios.rs

+ 14 - 2
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::<BasicMemoryInfoTag, _>(TagType::BasicMeminfo)
+    }
+
     /// Search for the ELF Sections tag.
     pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
         self.get_tag::<Tag, _>(TagType::ElfSections)
@@ -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 }
     }

+ 35 - 0
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)]

+ 69 - 0
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::<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]);
+    }
+}