Browse Source

multiboot2: Support passing the EFI System Table

Niklas Sombert 2 years ago
parent
commit
d5e99f72ae
2 changed files with 83 additions and 2 deletions
  1. 26 2
      multiboot2/src/builder/information.rs
  2. 57 0
      multiboot2/src/efi.rs

+ 26 - 2
multiboot2/src/builder/information.rs

@@ -1,8 +1,8 @@
 //! Exports item [`Multiboot2InformationBuilder`].
 use crate::builder::traits::StructAsBytes;
 use crate::{
-    BasicMemoryInfoTag, BootInformationInner, BootLoaderNameTag, CommandLineTag, ElfSectionsTag,
-    EndTag, FramebufferTag, MemoryMapTag, ModuleTag,
+    BasicMemoryInfoTag, BootInformationInner, BootLoaderNameTag, CommandLineTag, EFISdt32,
+    EFISdt64, ElfSectionsTag, EndTag, FramebufferTag, MemoryMapTag, ModuleTag,
 };
 
 use alloc::boxed::Box;
@@ -21,6 +21,8 @@ pub struct Multiboot2InformationBuilder {
     framebuffer_tag: Option<Box<FramebufferTag>>,
     memory_map_tag: Option<Box<MemoryMapTag>>,
     module_tags: Vec<Box<ModuleTag>>,
+    efisdt32: Option<EFISdt32>,
+    efisdt64: Option<EFISdt64>,
 }
 
 impl Multiboot2InformationBuilder {
@@ -29,6 +31,8 @@ impl Multiboot2InformationBuilder {
             basic_memory_info_tag: None,
             boot_loader_name_tag: None,
             command_line_tag: None,
+            efisdt32: None,
+            efisdt64: None,
             elf_sections_tag: None,
             framebuffer_tag: None,
             memory_map_tag: None,
@@ -66,6 +70,12 @@ impl Multiboot2InformationBuilder {
         if let Some(tag) = &self.command_line_tag {
             len += Self::size_or_up_aligned(tag.byte_size())
         }
+        if let Some(tag) = &self.efisdt32 {
+            len += Self::size_or_up_aligned(tag.byte_size())
+        }
+        if let Some(tag) = &self.efisdt64 {
+            len += Self::size_or_up_aligned(tag.byte_size())
+        }
         if let Some(tag) = &self.elf_sections_tag {
             len += Self::size_or_up_aligned(tag.byte_size())
         }
@@ -117,6 +127,12 @@ impl Multiboot2InformationBuilder {
         if let Some(tag) = self.command_line_tag.as_ref() {
             Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
         }
+        if let Some(tag) = self.efisdt32.as_ref() {
+            Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
+        }
+        if let Some(tag) = self.efisdt64.as_ref() {
+            Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
+        }
         if let Some(tag) = self.elf_sections_tag.as_ref() {
             Self::build_add_bytes(&mut data, &tag.struct_as_bytes(), false)
         }
@@ -147,6 +163,14 @@ impl Multiboot2InformationBuilder {
         self.command_line_tag = Some(command_line_tag);
     }
 
+    pub fn efisdt32(&mut self, efisdt32: EFISdt32) {
+        self.efisdt32 = Some(efisdt32);
+    }
+
+    pub fn efisdt64(&mut self, efisdt64: EFISdt64) {
+        self.efisdt64 = Some(efisdt64);
+    }
+
     pub fn elf_sections_tag(&mut self, elf_sections_tag: Box<ElfSectionsTag>) {
         self.elf_sections_tag = Some(elf_sections_tag);
     }

+ 57 - 0
multiboot2/src/efi.rs

@@ -1,6 +1,12 @@
 //! All MBI tags related to (U)EFI.
 
+use crate::TagType;
 use crate::TagTypeId;
+use core::convert::TryInto;
+use core::mem::size_of;
+
+#[cfg(feature = "builder")]
+use crate::builder::traits::StructAsBytes;
 
 /// EFI system table in 32 bit mode
 #[derive(Clone, Copy, Debug)]
@@ -12,12 +18,28 @@ pub struct EFISdt32 {
 }
 
 impl EFISdt32 {
+    /// Create a new tag to pass the EFI32 System Table pointer.
+    pub fn new(pointer: u32) -> Self {
+        Self {
+            typ: TagType::Efi32.into(),
+            size: size_of::<Self>().try_into().unwrap(),
+            pointer,
+        }
+    }
+
     /// The physical address of a i386 EFI system table.
     pub fn sdt_address(&self) -> usize {
         self.pointer as usize
     }
 }
 
+#[cfg(feature = "builder")]
+impl StructAsBytes for EFISdt32 {
+    fn byte_size(&self) -> usize {
+        size_of::<Self>()
+    }
+}
+
 /// EFI system table in 64 bit mode
 #[derive(Clone, Copy, Debug)]
 #[repr(C)]
@@ -28,12 +50,28 @@ pub struct EFISdt64 {
 }
 
 impl EFISdt64 {
+    /// Create a new tag to pass the EFI64 System Table pointer.
+    pub fn new(pointer: u64) -> Self {
+        Self {
+            typ: TagType::Efi64.into(),
+            size: size_of::<Self>().try_into().unwrap(),
+            pointer,
+        }
+    }
+
     /// The physical address of a x86_64 EFI system table.
     pub fn sdt_address(&self) -> usize {
         self.pointer as usize
     }
 }
 
+#[cfg(feature = "builder")]
+impl StructAsBytes for EFISdt64 {
+    fn byte_size(&self) -> usize {
+        size_of::<Self>()
+    }
+}
+
 /// Contains pointer to boot loader image handle.
 #[derive(Debug)]
 #[repr(C)]
@@ -65,3 +103,22 @@ impl EFIImageHandle64 {
         self.pointer as usize
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{EFISdt32, EFISdt64};
+
+    const ADDR: usize = 0xABCDEF;
+
+    #[test]
+    fn test_build_eftsdt32() {
+        let tag = EFISdt32::new(ADDR.try_into().unwrap());
+        assert_eq!(tag.sdt_address(), ADDR);
+    }
+
+    #[test]
+    fn test_build_eftsdt64() {
+        let tag = EFISdt64::new(ADDR.try_into().unwrap());
+        assert_eq!(tag.sdt_address(), ADDR);
+    }
+}