Skip to content

multiboot2: add missing tags #229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions multiboot2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

- dependency updates
- **Breaking:** MSRV is now 1.75
- Added missing tags:
- `ApmTag`
- `BootdevTag`
- `NetworkTag`

## v0.22.2 (2024-08-24)

Expand Down
126 changes: 126 additions & 0 deletions multiboot2/src/apm.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 67 additions & 0 deletions multiboot2/src/bootdev.rs
Original file line number Diff line number Diff line change
@@ -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;
}
42 changes: 39 additions & 3 deletions multiboot2/src/builder.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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>,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}
Expand All @@ -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());
}
Expand Down Expand Up @@ -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,
Expand All @@ -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]))
Expand All @@ -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))
Expand Down
8 changes: 3 additions & 5 deletions multiboot2/src/end.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
//! Module for [`EndTag`].

use crate::{TagHeader, TagType, TagTypeId};
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 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),
}
}
}
Expand Down
Loading