Browse Source

Added multiboot2 module support

This is not very complex of an addition, but it has
its quirks. First, there can be multiple module tags
in the multiboot info structure. Because of this a
ModuleIter would include a modified TagIter or TagIter
would need a get_next_tag(x) method. Secondly the tag
contiains a string at the end that I use an unchecked
conversion to access. I think this is fine though because
this method is already used in boot_loader_name.rs.
Calvin Lee 8 years ago
parent
commit
c1c65b4d2f
2 changed files with 37 additions and 0 deletions
  1. 6 0
      src/lib.rs
  2. 31 0
      src/module.rs

+ 6 - 0
src/lib.rs

@@ -4,6 +4,7 @@ pub use boot_loader_name::BootLoaderNameTag;
 pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
 pub use elf_sections::{ELF_SECTION_WRITABLE, ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE};
 pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
+pub use module::{ModuleTag};
 
 #[macro_use]
 extern crate bitflags;
@@ -11,6 +12,7 @@ extern crate bitflags;
 mod boot_loader_name;
 mod elf_sections;
 mod memory_map;
+mod module;
 
 pub unsafe fn load(address: usize) -> &'static BootInformation {
     let multiboot = &*(address as *const BootInformation);
@@ -42,6 +44,10 @@ impl BootInformation {
         self.get_tag(6).map(|tag| unsafe{&*(tag as *const Tag as *const MemoryMapTag)})
     }
 
+    pub fn module_tag(&self) -> Option<&'static ModuleTag> {
+        self.get_tag(3).map(|tag| unsafe{&*(tag as *const Tag as *const ModuleTag)})
+    }
+
     pub fn boot_loader_name_tag(&self) -> Option<&'static BootLoaderNameTag> {
         self.get_tag(2).map(|tag| unsafe{&*(tag as *const Tag as *const BootLoaderNameTag)})
     }

+ 31 - 0
src/module.rs

@@ -0,0 +1,31 @@
+#[repr(packed)]
+#[derive(Debug)]
+pub struct ModuleTag {
+    typ: u32,
+    size: u32,
+    mod_start: u32,
+    mod_end: u32,
+    name_byte: u8,
+}
+
+impl ModuleTag {
+    // The multiboot specification defines the module str
+    // as valid utf-8, therefore this function produces
+    // defined behavior
+    pub fn name(&self) -> &str {
+        use core::{mem,str,slice};
+        let strlen = self.size as usize - mem::size_of::<ModuleTag>();
+        unsafe {
+            str::from_utf8_unchecked(
+                slice::from_raw_parts(&self.name_byte as *const u8, strlen))
+        }
+    }
+
+    pub fn start_address(&self) -> u32 {
+        self.mod_start
+    }
+
+    pub fn end_address(&self) -> u32 {
+        self.mod_end
+    }
+}