Browse Source

multiboot2: add BootdevTag

Philipp Schuster 7 months ago
parent
commit
3d1fdf7904
4 changed files with 87 additions and 5 deletions
  1. 1 0
      multiboot2/CHANGELOG.md
  2. 67 0
      multiboot2/src/bootdev.rs
  3. 17 5
      multiboot2/src/builder.rs
  4. 2 0
      multiboot2/src/lib.rs

+ 1 - 0
multiboot2/CHANGELOG.md

@@ -6,6 +6,7 @@
 - **Breaking:** MSRV is now 1.75
 - Added missing tags:
     - `ApmTag`
+    - `BootdevTag`
 
 ## v0.22.2 (2024-08-24)
 

+ 67 - 0
multiboot2/src/bootdev.rs

@@ -0,0 +1,67 @@
+//! Module for [`BootdevTag`].
+
+use crate::{TagHeader, TagType};
+use core::mem;
+use multiboot2_common::{MaybeDynSized, Tag};
+
+/// The end tag ends the information struct.
+#[derive(Debug)]
+#[repr(C, align(8))]
+pub struct BootdevTag {
+    header: TagHeader,
+    biosdev: u32,
+    slice: u32,
+    part: u32,
+}
+
+impl BootdevTag {
+    /// Creates a new tag.
+    #[must_use]
+    pub fn new(biosdev: u32, slice: u32, part: u32) -> Self {
+        Self {
+            header: TagHeader::new(TagType::Apm, mem::size_of::<Self>() as u32),
+            biosdev,
+            slice,
+            part,
+        }
+    }
+
+    /// Returns the bios device from which the device was booted from.
+    /// `0x00` represents the first floppy disk.
+    /// `0x80` represents the first hard disk, 0x81 the second hard disk, and
+    /// so on.
+    #[must_use]
+    pub const fn biosdev(&self) -> u32 {
+        self.biosdev
+    }
+
+    /// The slice field identifies the partition (also known as a "slice" in BSD
+    /// terminology) on the BIOS device from which the operating system was
+    /// booted.
+    #[must_use]
+    pub const fn slice(&self) -> u32 {
+        self.slice
+    }
+
+    /// The part field denotes the subpartition or logical partition within the
+    /// primary partition (if applicable) from which the operating system was
+    /// booted.
+    #[must_use]
+    pub const fn part(&self) -> u32 {
+        self.part
+    }
+}
+
+impl MaybeDynSized for BootdevTag {
+    type Header = TagHeader;
+
+    const BASE_SIZE: usize = mem::size_of::<Self>();
+
+    fn dst_len(_: &TagHeader) {}
+}
+
+impl Tag for BootdevTag {
+    type IDType = TagType;
+
+    const ID: TagType = TagType::Bootdev;
+}

+ 17 - 5
multiboot2/src/builder.rs

@@ -1,6 +1,7 @@
 //! Module for [`Builder`].
 
 use crate::apm::ApmTag;
+use crate::bootdev::BootdevTag;
 use crate::{
     BasicMemoryInfoTag, BootInformationHeader, BootLoaderNameTag, CommandLineTag,
     EFIBootServicesNotExitedTag, EFIImageHandle32Tag, EFIImageHandle64Tag, EFIMemoryMapTag,
@@ -19,7 +20,7 @@ pub struct Builder {
     bootloader: Option<Box<BootLoaderNameTag>>,
     modules: Vec<Box<ModuleTag>>,
     meminfo: Option<BasicMemoryInfoTag>,
-    // missing bootdev: Option<BootDevice>
+    bootdev: Option<BootdevTag>,
     mmap: Option<Box<MemoryMapTag>>,
     vbe: Option<VBEInfoTag>,
     framebuffer: Option<Box<FramebufferTag>>,
@@ -54,6 +55,7 @@ impl Builder {
             bootloader: None,
             modules: vec![],
             meminfo: None,
+            bootdev: None,
             mmap: None,
             vbe: None,
             framebuffer: None,
@@ -101,6 +103,13 @@ impl Builder {
         self
     }
 
+    /// Sets the [`BootdevTag`] tag.
+    #[must_use]
+    pub const fn bootdev(mut self, bootdev: BootdevTag) -> Self {
+        self.bootdev = Some(bootdev);
+        self
+    }
+
     /// Sets the [`MemoryMapTag`] tag.
     #[must_use]
     pub fn mmap(mut self, mmap: Box<MemoryMapTag>) -> Self {
@@ -131,7 +140,7 @@ impl Builder {
 
     /// Sets the [`ApmTag`] tag.
     #[must_use]
-    pub fn apm(mut self, apm: ApmTag) -> Self {
+    pub const fn apm(mut self, apm: ApmTag) -> Self {
         self.apm = Some(apm);
         self
     }
@@ -223,9 +232,6 @@ impl Builder {
     pub fn build(self) -> Box<DynSizedStructure<BootInformationHeader>> {
         let header = BootInformationHeader::new(0);
         let mut byte_refs = Vec::new();
-        if let Some(tag) = self.apm.as_ref() {
-            byte_refs.push(tag.as_bytes().as_ref());
-        }
         if let Some(tag) = self.cmdline.as_ref() {
             byte_refs.push(tag.as_bytes().as_ref());
         }
@@ -238,6 +244,9 @@ impl Builder {
         if let Some(tag) = self.meminfo.as_ref() {
             byte_refs.push(tag.as_bytes().as_ref());
         }
+        if let Some(tag) = self.bootdev.as_ref() {
+            byte_refs.push(tag.as_bytes().as_ref());
+        }
         if let Some(tag) = self.mmap.as_ref() {
             byte_refs.push(tag.as_bytes().as_ref());
         }
@@ -308,6 +317,7 @@ mod tests {
             .add_module(ModuleTag::new(0x1000, 0x2000, "module 1"))
             .add_module(ModuleTag::new(0x3000, 0x4000, "module 2"))
             .meminfo(BasicMemoryInfoTag::new(0x4000, 0x5000))
+            .bootdev(BootdevTag::new(0x00, 0x00, 0x00))
             .mmap(MemoryMapTag::new(&[MemoryArea::new(
                 0x1000000,
                 0x1000,
@@ -331,6 +341,7 @@ mod tests {
                 FramebufferType::Text,
             ))
             .elf_sections(ElfSectionsTag::new(0, 32, 0, &[]))
+            .apm(ApmTag::new(0, 0, 0, 0, 0, 0, 0, 0, 0))
             .efi32(EFISdt32Tag::new(0x1000))
             .efi64(EFISdt64Tag::new(0x1000))
             .add_smbios(SmbiosTag::new(0, 0, &[1, 2, 3]))
@@ -341,6 +352,7 @@ mod tests {
                 MemoryDescriptor::default(),
                 MemoryDescriptor::default(),
             ]))
+            .network(NetworkTag::new(&[0; 1500]))
             .efi_bs(EFIBootServicesNotExitedTag::new())
             .efi32_ih(EFIImageHandle32Tag::new(0x1000))
             .efi64_ih(EFIImageHandle64Tag::new(0x1000))

+ 2 - 0
multiboot2/src/lib.rs

@@ -69,6 +69,7 @@ pub type GenericInfoTag = multiboot2_common::DynSizedStructure<TagHeader>;
 mod apm;
 mod boot_information;
 mod boot_loader_name;
+mod bootdev;
 mod command_line;
 mod efi;
 mod elf_sections;
@@ -89,6 +90,7 @@ pub use multiboot2_common::{DynSizedStructure, MaybeDynSized, Tag};
 pub use apm::ApmTag;
 pub use boot_information::{BootInformation, BootInformationHeader, LoadError};
 pub use boot_loader_name::BootLoaderNameTag;
+pub use bootdev::BootdevTag;
 #[cfg(feature = "builder")]
 pub use builder::Builder;
 pub use command_line::CommandLineTag;