瀏覽代碼

Merge pull request #229 from rust-osdev/tags

multiboot2: add missing tags
Philipp Schuster 7 月之前
父節點
當前提交
2395918075
共有 7 個文件被更改,包括 288 次插入8 次删除
  1. 4 0
      multiboot2/CHANGELOG.md
  2. 126 0
      multiboot2/src/apm.rs
  3. 67 0
      multiboot2/src/bootdev.rs
  4. 39 3
      multiboot2/src/builder.rs
  5. 3 5
      multiboot2/src/end.rs
  6. 6 0
      multiboot2/src/lib.rs
  7. 43 0
      multiboot2/src/network.rs

+ 4 - 0
multiboot2/CHANGELOG.md

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

+ 126 - 0
multiboot2/src/apm.rs

@@ -0,0 +1,126 @@
+//! Module for [`ApmTag`].
+
+use crate::{TagHeader, TagType};
+use core::mem;
+use multiboot2_common::{MaybeDynSized, Tag};
+
+/// The Advanced Power Management (APM) tag.
+#[derive(Debug)]
+#[repr(C, align(8))]
+pub struct ApmTag {
+    header: TagHeader,
+    version: u16,
+    cseg: u16,
+    offset: u32,
+    cset_16: u16,
+    dseg: u16,
+    flags: u16,
+    cseg_len: u16,
+    cseg_16_len: u16,
+    dseg_len: u16,
+}
+
+impl ApmTag {
+    /// Creates a new tag.
+    #[allow(clippy::too_many_arguments)]
+    #[must_use]
+    pub fn new(
+        version: u16,
+        cseg: u16,
+        offset: u32,
+        cset_16: u16,
+        dset: u16,
+        flags: u16,
+        cseg_len: u16,
+        cseg_16_len: u16,
+        dseg_len: u16,
+    ) -> Self {
+        Self {
+            header: TagHeader::new(TagType::Apm, mem::size_of::<Self>() as u32),
+            version,
+            cseg,
+            offset,
+            cset_16,
+            dseg: dset,
+            flags,
+            cseg_len,
+            cseg_16_len,
+            dseg_len,
+        }
+    }
+
+    /// The version number of the APM BIOS.
+    #[must_use]
+    pub const fn version(&self) -> u16 {
+        self.version
+    }
+
+    /// Contains the 16-bit code segment (CS) address for the APM entry point.
+    #[must_use]
+    pub const fn cseg(&self) -> u16 {
+        self.cseg
+    }
+
+    /// Represents the offset address within the code segment (`cseg`) for the
+    /// APM entry point.
+    #[must_use]
+    pub const fn offset(&self) -> u32 {
+        self.offset
+    }
+
+    /// Contains the 16-bit code segment (CS) address used for 16-bit protected
+    /// mode APM functions.
+    #[must_use]
+    pub const fn cset_16(&self) -> u16 {
+        self.cset_16
+    }
+
+    /// Holds the 16-bit data segment (DS) address used by the APM BIOS for
+    /// data operations.
+    #[must_use]
+    pub const fn dseg(&self) -> u16 {
+        self.dseg
+    }
+
+    /// Indicates the status and characteristics of the APM connection, such as
+    /// if APM is present and its capabilities.
+    #[must_use]
+    pub const fn flags(&self) -> u16 {
+        self.flags
+    }
+
+    /// Indicates the length, in bytes, of the data segment (`dseg`) used by
+    /// the APM BIOS
+    #[must_use]
+    pub const fn cseg_len(&self) -> u16 {
+        self.cseg_len
+    }
+
+    /// Provides the length, in bytes, of the 16-bit code segment (`cseg_16`)
+    /// used for APM functions.
+    #[must_use]
+    pub const fn cseg_16_len(&self) -> u16 {
+        self.cseg_16_len
+    }
+
+    /// Indicates the length, in bytes, of the data segment (`dseg`) used by
+    /// the APM BIOS.
+    #[must_use]
+    pub const fn dseg_len(&self) -> u16 {
+        self.dseg_len
+    }
+}
+
+impl MaybeDynSized for ApmTag {
+    type Header = TagHeader;
+
+    const BASE_SIZE: usize = mem::size_of::<Self>();
+
+    fn dst_len(_: &TagHeader) {}
+}
+
+impl Tag for ApmTag {
+    type IDType = TagType;
+
+    const ID: TagType = TagType::Apm;
+}

+ 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;
+}

+ 39 - 3
multiboot2/src/builder.rs

@@ -1,5 +1,8 @@
 //! Module for [`Builder`].
 
+use crate::apm::ApmTag;
+use crate::bootdev::BootdevTag;
+use crate::network::NetworkTag;
 use crate::{
     BasicMemoryInfoTag, BootInformationHeader, BootLoaderNameTag, CommandLineTag,
     EFIBootServicesNotExitedTag, EFIImageHandle32Tag, EFIImageHandle64Tag, EFIMemoryMapTag,
@@ -18,18 +21,18 @@ 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>>,
     elf_sections: Option<Box<ElfSectionsTag>>,
-    // missing apm:
+    apm: Option<ApmTag>,
     efi32: Option<EFISdt32Tag>,
     efi64: Option<EFISdt64Tag>,
     smbios: Vec<Box<SmbiosTag>>,
     rsdpv1: Option<RsdpV1Tag>,
     rsdpv2: Option<RsdpV2Tag>,
-    // missing: network
+    network: Option<Box<NetworkTag>>,
     efi_mmap: Option<Box<EFIMemoryMapTag>>,
     efi_bs: Option<EFIBootServicesNotExitedTag>,
     efi32_ih: Option<EFIImageHandle32Tag>,
@@ -53,16 +56,19 @@ impl Builder {
             bootloader: None,
             modules: vec![],
             meminfo: None,
+            bootdev: None,
             mmap: None,
             vbe: None,
             framebuffer: None,
             elf_sections: None,
+            apm: None,
             efi32: None,
             efi64: None,
             smbios: vec![],
             rsdpv1: None,
             rsdpv2: None,
             efi_mmap: None,
+            network: None,
             efi_bs: None,
             efi32_ih: None,
             efi64_ih: None,
@@ -99,6 +105,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 {
@@ -127,6 +140,13 @@ impl Builder {
         self
     }
 
+    /// Sets the [`ApmTag`] tag.
+    #[must_use]
+    pub const fn apm(mut self, apm: ApmTag) -> Self {
+        self.apm = Some(apm);
+        self
+    }
+
     /// Sets the [`EFISdt32Tag`] tag.
     #[must_use]
     pub const fn efi32(mut self, efi32: EFISdt32Tag) -> Self {
@@ -169,6 +189,13 @@ impl Builder {
         self
     }
 
+    /// Sets the [`NetworkTag`] tag.
+    #[must_use]
+    pub fn network(mut self, network: Box<NetworkTag>) -> Self {
+        self.network = Some(network);
+        self
+    }
+
     /// Sets the [`EFIBootServicesNotExitedTag`] tag.
     #[must_use]
     pub const fn efi_bs(mut self, efi_bs: EFIBootServicesNotExitedTag) -> Self {
@@ -226,6 +253,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());
         }
@@ -238,6 +268,9 @@ impl Builder {
         if let Some(tag) = self.elf_sections.as_ref() {
             byte_refs.push(tag.as_bytes().as_ref());
         }
+        if let Some(tag) = self.apm.as_ref() {
+            byte_refs.push(tag.as_bytes().as_ref());
+        }
         if let Some(tag) = self.efi32.as_ref() {
             byte_refs.push(tag.as_bytes().as_ref());
         }
@@ -293,6 +326,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,
@@ -316,6 +350,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]))
@@ -326,6 +361,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))

+ 3 - 5
multiboot2/src/end.rs

@@ -1,6 +1,6 @@
 //! Module for [`EndTag`].
 
-use crate::{TagHeader, TagType, TagTypeId};
+use crate::{TagHeader, TagType};
 use core::mem;
 use multiboot2_common::{MaybeDynSized, Tag};
 
@@ -8,15 +8,13 @@ use multiboot2_common::{MaybeDynSized, Tag};
 #[derive(Debug)]
 #[repr(C, align(8))]
 pub struct EndTag {
-    typ: TagTypeId,
-    size: u32,
+    header: TagHeader,
 }
 
 impl Default for EndTag {
     fn default() -> Self {
         Self {
-            typ: TagType::End.into(),
-            size: 8,
+            header: TagHeader::new(TagType::End, mem::size_of::<Self>() as u32),
         }
     }
 }

+ 6 - 0
multiboot2/src/lib.rs

@@ -66,8 +66,10 @@ pub type TagIter<'a> = multiboot2_common::TagIter<'a, TagHeader>;
 #[cfg(test)]
 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;
@@ -76,6 +78,7 @@ mod framebuffer;
 mod image_load_addr;
 mod memory_map;
 mod module;
+mod network;
 mod rsdp;
 mod smbios;
 mod tag;
@@ -85,8 +88,10 @@ mod vbe_info;
 
 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;
@@ -104,6 +109,7 @@ pub use memory_map::{
     MemoryArea, MemoryAreaType, MemoryAreaTypeId, MemoryMapTag,
 };
 pub use module::{ModuleIter, ModuleTag};
+pub use network::NetworkTag;
 pub use ptr_meta::Pointee;
 pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
 pub use smbios::SmbiosTag;

+ 43 - 0
multiboot2/src/network.rs

@@ -0,0 +1,43 @@
+//! Module for [`NetworkTag`].
+
+use crate::{TagHeader, TagType, TagTypeId};
+use core::mem;
+use multiboot2_common::{MaybeDynSized, Tag};
+use ptr_meta::Pointee;
+#[cfg(feature = "builder")]
+use {alloc::boxed::Box, multiboot2_common::new_boxed};
+
+/// The end tag ends the information struct.
+#[derive(Debug, Pointee)]
+#[repr(C, align(8))]
+pub struct NetworkTag {
+    typ: TagTypeId,
+    size: u32,
+    dhcpack: [u8],
+}
+
+impl NetworkTag {
+    /// Create a new network tag from the given DHCP package.
+    #[cfg(feature = "builder")]
+    #[must_use]
+    pub fn new(dhcp_pack: &[u8]) -> Box<Self> {
+        let header = TagHeader::new(Self::ID, 0);
+        new_boxed(header, &[dhcp_pack])
+    }
+}
+
+impl MaybeDynSized for NetworkTag {
+    type Header = TagHeader;
+
+    const BASE_SIZE: usize = mem::size_of::<TagHeader>();
+
+    fn dst_len(header: &TagHeader) -> usize {
+        header.size as usize - Self::BASE_SIZE
+    }
+}
+
+impl Tag for NetworkTag {
+    type IDType = TagType;
+
+    const ID: TagType = TagType::Network;
+}