Browse Source

multiboot2: Implement adding module tags

Niklas Sombert 2 years ago
parent
commit
535c9e777c
2 changed files with 30 additions and 8 deletions
  1. 7 1
      multiboot2/src/builder/information.rs
  2. 23 7
      multiboot2/src/module.rs

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

@@ -1,5 +1,5 @@
 //! Exports item [`Multiboot2InformationBuilder`].
-use crate::{builder::traits::StructAsBytes, CommandLineTag};
+use crate::{builder::traits::StructAsBytes, CommandLineTag, ModuleTag};
 
 use alloc::boxed::Box;
 use alloc::vec::Vec;
@@ -10,16 +10,22 @@ use alloc::vec::Vec;
 #[derive(Debug)]
 pub struct Multiboot2InformationBuilder {
     command_line_tag: Option<Box<CommandLineTag>>,
+    module_tags: Vec<Box<ModuleTag>>,
 }
 
 impl Multiboot2InformationBuilder {
     pub const fn new() -> Self {
         Self {
             command_line_tag: None,
+            module_tags: Vec::new(),
         }
     }
 
     pub fn command_line_tag(&mut self, command_line_tag: Box<CommandLineTag>) {
         self.command_line_tag = Some(command_line_tag);
     }
+
+    pub fn add_module_tag(&mut self, module_tag: Box<ModuleTag>) {
+        self.module_tags.push(module_tag);
+    }
 }

+ 23 - 7
multiboot2/src/module.rs

@@ -1,9 +1,14 @@
-use crate::tag_type::{Tag, TagIter, TagType};
-use crate::TagTrait;
-use crate::TagTypeId;
+use crate::{Tag, TagIter, TagTrait, TagType, TagTypeId};
+
 use core::fmt::{Debug, Formatter};
+use core::mem::size_of;
 use core::str::Utf8Error;
 
+#[cfg(feature = "builder")]
+use {crate::builder::boxed_dst_tag, alloc::boxed::Box, alloc::vec::Vec};
+
+const METADATA_SIZE: usize = size_of::<TagTypeId>() + 3 * size_of::<u32>();
+
 /// This tag indicates to the kernel what boot module was loaded along with
 /// the kernel image, and where it can be found.
 #[repr(C, packed)] // only repr(C) would add unwanted padding near name_byte.
@@ -18,8 +23,21 @@ pub struct ModuleTag {
 }
 
 impl ModuleTag {
+    #[cfg(feature = "builder")]
+    pub fn new(start: u32, end: u32, cmdline: &str) -> Box<Self> {
+        let mut cmdline_bytes: Vec<_> = cmdline.bytes().collect();
+        cmdline_bytes.push(0);
+        let start_bytes = start.to_le_bytes();
+        let end_bytes = end.to_le_bytes();
+        let mut content_bytes = [start_bytes, end_bytes].concat();
+        content_bytes.extend_from_slice(&cmdline_bytes);
+        boxed_dst_tag(TagType::Module, &content_bytes)
+    }
+
     /// Reads the command line of the boot module as Rust string slice without
     /// the null-byte.
+    /// This is an null-terminated UTF-8 string. If this returns `Err` then perhaps the memory
+    /// is invalid or the bootloader doesn't follow the spec.
     ///
     /// For example, this returns `"--test cmdline-option"`.if the GRUB config
     /// contains  `"module2 /some_boot_module --test cmdline-option"`.
@@ -47,10 +65,8 @@ impl ModuleTag {
 
 impl TagTrait for ModuleTag {
     fn dst_size(base_tag: &Tag) -> usize {
-        // The size of the sized portion of the module tag.
-        let tag_base_size = 16;
-        assert!(base_tag.size >= 8);
-        base_tag.size as usize - tag_base_size
+        assert!(base_tag.size as usize >= METADATA_SIZE);
+        base_tag.size as usize - METADATA_SIZE
     }
 }