From 17e48f8bebfc415598f3afcfe6f686e6935ff8b5 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 1 Sep 2024 12:26:36 +0200 Subject: [PATCH 1/4] multiboot2: add ApmTag --- multiboot2/CHANGELOG.md | 2 + multiboot2/src/apm.rs | 126 ++++++++++++++++++++++++++++++++++++++ multiboot2/src/builder.rs | 17 ++++- multiboot2/src/lib.rs | 2 + 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 multiboot2/src/apm.rs diff --git a/multiboot2/CHANGELOG.md b/multiboot2/CHANGELOG.md index cbec0eec..62e1a664 100644 --- a/multiboot2/CHANGELOG.md +++ b/multiboot2/CHANGELOG.md @@ -4,6 +4,8 @@ - dependency updates - **Breaking:** MSRV is now 1.75 +- Added missing tags: + - `ApmTag` ## v0.22.2 (2024-08-24) diff --git a/multiboot2/src/apm.rs b/multiboot2/src/apm.rs new file mode 100644 index 00000000..11211a36 --- /dev/null +++ b/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::() 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::(); + + fn dst_len(_: &TagHeader) {} +} + +impl Tag for ApmTag { + type IDType = TagType; + + const ID: TagType = TagType::Apm; +} diff --git a/multiboot2/src/builder.rs b/multiboot2/src/builder.rs index 6ee4dea6..1dbd55b2 100644 --- a/multiboot2/src/builder.rs +++ b/multiboot2/src/builder.rs @@ -1,5 +1,6 @@ //! Module for [`Builder`]. +use crate::apm::ApmTag; use crate::{ BasicMemoryInfoTag, BootInformationHeader, BootLoaderNameTag, CommandLineTag, EFIBootServicesNotExitedTag, EFIImageHandle32Tag, EFIImageHandle64Tag, EFIMemoryMapTag, @@ -23,7 +24,7 @@ pub struct Builder { vbe: Option, framebuffer: Option>, elf_sections: Option>, - // missing apm: + apm: Option, efi32: Option, efi64: Option, smbios: Vec>, @@ -57,6 +58,7 @@ impl Builder { vbe: None, framebuffer: None, elf_sections: None, + apm: None, efi32: None, efi64: None, smbios: vec![], @@ -127,6 +129,13 @@ impl Builder { self } + /// Sets the [`ApmTag`] tag. + #[must_use] + pub 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 { @@ -214,6 +223,9 @@ impl Builder { pub fn build(self) -> Box> { 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 +250,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()); } diff --git a/multiboot2/src/lib.rs b/multiboot2/src/lib.rs index d5ad47c5..bc8e28bd 100644 --- a/multiboot2/src/lib.rs +++ b/multiboot2/src/lib.rs @@ -66,6 +66,7 @@ pub type TagIter<'a> = multiboot2_common::TagIter<'a, TagHeader>; #[cfg(test)] pub type GenericInfoTag = multiboot2_common::DynSizedStructure; +mod apm; mod boot_information; mod boot_loader_name; mod command_line; @@ -85,6 +86,7 @@ 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; #[cfg(feature = "builder")] From 3d1fdf790414d0a6f8aa9cc50abd4cf49db83aae Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 1 Sep 2024 12:08:47 +0200 Subject: [PATCH 2/4] multiboot2: add BootdevTag --- multiboot2/CHANGELOG.md | 1 + multiboot2/src/bootdev.rs | 67 +++++++++++++++++++++++++++++++++++++++ multiboot2/src/builder.rs | 22 ++++++++++--- multiboot2/src/lib.rs | 2 ++ 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 multiboot2/src/bootdev.rs diff --git a/multiboot2/CHANGELOG.md b/multiboot2/CHANGELOG.md index 62e1a664..753df6ec 100644 --- a/multiboot2/CHANGELOG.md +++ b/multiboot2/CHANGELOG.md @@ -6,6 +6,7 @@ - **Breaking:** MSRV is now 1.75 - Added missing tags: - `ApmTag` + - `BootdevTag` ## v0.22.2 (2024-08-24) diff --git a/multiboot2/src/bootdev.rs b/multiboot2/src/bootdev.rs new file mode 100644 index 00000000..14640e16 --- /dev/null +++ b/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::() 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::(); + + fn dst_len(_: &TagHeader) {} +} + +impl Tag for BootdevTag { + type IDType = TagType; + + const ID: TagType = TagType::Bootdev; +} diff --git a/multiboot2/src/builder.rs b/multiboot2/src/builder.rs index 1dbd55b2..d65d3b00 100644 --- a/multiboot2/src/builder.rs +++ b/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>, modules: Vec>, meminfo: Option, - // missing bootdev: Option + bootdev: Option, mmap: Option>, vbe: Option, framebuffer: Option>, @@ -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) -> 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> { 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)) diff --git a/multiboot2/src/lib.rs b/multiboot2/src/lib.rs index bc8e28bd..a1bed316 100644 --- a/multiboot2/src/lib.rs +++ b/multiboot2/src/lib.rs @@ -69,6 +69,7 @@ pub type GenericInfoTag = multiboot2_common::DynSizedStructure; 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; From 2698ed3efda40b2ed3261225a54915acf37ba729 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 1 Sep 2024 12:19:49 +0200 Subject: [PATCH 3/4] multiboot2: add NetworkTag --- multiboot2/CHANGELOG.md | 1 + multiboot2/src/builder.rs | 11 +++++++++- multiboot2/src/lib.rs | 2 ++ multiboot2/src/network.rs | 43 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 multiboot2/src/network.rs diff --git a/multiboot2/CHANGELOG.md b/multiboot2/CHANGELOG.md index 753df6ec..6fe1b347 100644 --- a/multiboot2/CHANGELOG.md +++ b/multiboot2/CHANGELOG.md @@ -7,6 +7,7 @@ - Added missing tags: - `ApmTag` - `BootdevTag` + - `NetworkTag` ## v0.22.2 (2024-08-24) diff --git a/multiboot2/src/builder.rs b/multiboot2/src/builder.rs index d65d3b00..0ddab5de 100644 --- a/multiboot2/src/builder.rs +++ b/multiboot2/src/builder.rs @@ -2,6 +2,7 @@ use crate::apm::ApmTag; use crate::bootdev::BootdevTag; +use crate::network::NetworkTag; use crate::{ BasicMemoryInfoTag, BootInformationHeader, BootLoaderNameTag, CommandLineTag, EFIBootServicesNotExitedTag, EFIImageHandle32Tag, EFIImageHandle64Tag, EFIMemoryMapTag, @@ -31,7 +32,7 @@ pub struct Builder { smbios: Vec>, rsdpv1: Option, rsdpv2: Option, - // missing: network + network: Option>, efi_mmap: Option>, efi_bs: Option, efi32_ih: Option, @@ -67,6 +68,7 @@ impl Builder { rsdpv1: None, rsdpv2: None, efi_mmap: None, + network: None, efi_bs: None, efi32_ih: None, efi64_ih: None, @@ -187,6 +189,13 @@ impl Builder { self } + /// Sets the [`NetworkTag`] tag. + #[must_use] + pub fn network(mut self, network: Box) -> Self { + self.network = Some(network); + self + } + /// Sets the [`EFIBootServicesNotExitedTag`] tag. #[must_use] pub const fn efi_bs(mut self, efi_bs: EFIBootServicesNotExitedTag) -> Self { diff --git a/multiboot2/src/lib.rs b/multiboot2/src/lib.rs index a1bed316..cd13f558 100644 --- a/multiboot2/src/lib.rs +++ b/multiboot2/src/lib.rs @@ -78,6 +78,7 @@ mod framebuffer; mod image_load_addr; mod memory_map; mod module; +mod network; mod rsdp; mod smbios; mod tag; @@ -108,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; diff --git a/multiboot2/src/network.rs b/multiboot2/src/network.rs new file mode 100644 index 00000000..1cea90b7 --- /dev/null +++ b/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 { + 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::(); + + 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; +} From b14070db0b0970ea7b5dc48eae570d416724b1ac Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 1 Sep 2024 12:31:57 +0200 Subject: [PATCH 4/4] multiboot2: end tag nit --- multiboot2/src/end.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/multiboot2/src/end.rs b/multiboot2/src/end.rs index d8f900c4..23707d0b 100644 --- a/multiboot2/src/end.rs +++ b/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::() as u32), } } }