Browse Source

multiboot2: Allow setting the SMBIOS tag

Niklas Sombert 2 years ago
parent
commit
888dd27742
2 changed files with 45 additions and 2 deletions
  1. 13 1
      multiboot2/src/builder/information.rs
  2. 32 1
      multiboot2/src/smbios.rs

+ 13 - 1
multiboot2/src/builder/information.rs

@@ -2,7 +2,7 @@
 use crate::builder::traits::StructAsBytes;
 use crate::{
     BasicMemoryInfoTag, BootInformationInner, BootLoaderNameTag, CommandLineTag, EFISdt32,
-    EFISdt64, ElfSectionsTag, EndTag, FramebufferTag, MemoryMapTag, ModuleTag,
+    EFISdt64, ElfSectionsTag, EndTag, FramebufferTag, MemoryMapTag, ModuleTag, SmbiosTag,
 };
 
 use alloc::boxed::Box;
@@ -23,6 +23,7 @@ pub struct Multiboot2InformationBuilder {
     module_tags: Vec<Box<ModuleTag>>,
     efisdt32: Option<EFISdt32>,
     efisdt64: Option<EFISdt64>,
+    smbios_tags: Vec<Box<SmbiosTag>>,
 }
 
 impl Multiboot2InformationBuilder {
@@ -37,6 +38,7 @@ impl Multiboot2InformationBuilder {
             framebuffer_tag: None,
             memory_map_tag: None,
             module_tags: Vec::new(),
+            smbios_tags: Vec::new(),
         }
     }
 
@@ -88,6 +90,9 @@ impl Multiboot2InformationBuilder {
         for tag in &self.module_tags {
             len += Self::size_or_up_aligned(tag.byte_size())
         }
+        for tag in &self.smbios_tags {
+            len += Self::size_or_up_aligned(tag.byte_size())
+        }
         // only here size_or_up_aligned is not important, because it is the last tag
         len += size_of::<EndTag>();
         len
@@ -145,6 +150,9 @@ impl Multiboot2InformationBuilder {
         for tag in self.module_tags {
             Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
         }
+        for tag in self.smbios_tags {
+            Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
+        }
 
         Self::build_add_bytes(&mut data, &EndTag::default().struct_as_bytes(), true);
 
@@ -186,6 +194,10 @@ impl Multiboot2InformationBuilder {
     pub fn add_module_tag(&mut self, module_tag: Box<ModuleTag>) {
         self.module_tags.push(module_tag);
     }
+
+    pub fn add_smbios_tag(&mut self, smbios_tag: Box<SmbiosTag>) {
+        self.smbios_tags.push(smbios_tag);
+    }
 }
 
 #[cfg(test)]

+ 32 - 1
multiboot2/src/smbios.rs

@@ -1,7 +1,11 @@
-use crate::{Tag, TagTrait, TagTypeId};
+use crate::{Tag, TagTrait, TagType, TagTypeId};
 
+use core::convert::TryInto;
 use core::fmt::Debug;
 
+#[cfg(feature = "builder")]
+use {crate::builder::boxed_dst_tag, crate::builder::traits::StructAsBytes, alloc::boxed::Box};
+
 const METADATA_SIZE: usize = core::mem::size_of::<TagTypeId>()
     + core::mem::size_of::<u32>()
     + core::mem::size_of::<u8>() * 8;
@@ -18,6 +22,15 @@ pub struct SmbiosTag {
     pub tables: [u8],
 }
 
+impl SmbiosTag {
+    #[cfg(feature = "builder")]
+    pub fn new(major: u8, minor: u8, tables: &[u8]) -> Box<Self> {
+        let mut bytes = [major, minor, 0, 0, 0, 0, 0, 0].to_vec();
+        bytes.extend(tables);
+        boxed_dst_tag(TagType::Smbios, &bytes)
+    }
+}
+
 impl TagTrait for SmbiosTag {
     fn dst_size(base_tag: &Tag) -> usize {
         assert!(base_tag.size as usize >= METADATA_SIZE);
@@ -25,6 +38,13 @@ impl TagTrait for SmbiosTag {
     }
 }
 
+#[cfg(feature = "builder")]
+impl StructAsBytes for SmbiosTag {
+    fn byte_size(&self) -> usize {
+        self.size.try_into().unwrap()
+    }
+}
+
 impl Debug for SmbiosTag {
     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
         f.debug_struct("BootLoaderNameTag")
@@ -66,4 +86,15 @@ mod tests {
         assert_eq!(tag.minor, 0);
         assert_eq!(tag.tables, [0xabu8; 24]);
     }
+
+    /// Test to generate a tag.
+    #[test]
+    #[cfg(feature = "builder")]
+    fn test_build() {
+        use crate::builder::traits::StructAsBytes;
+
+        let tag = SmbiosTag::new(3, 0, &[0xabu8; 24]);
+        let bytes = tag.struct_as_bytes();
+        assert_eq!(bytes, get_bytes());
+    }
 }