multiboot2_header/
relocatable.rs1use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType};
2use core::fmt;
3use core::fmt::{Debug, Formatter};
4use core::mem;
5use multiboot2_common::{MaybeDynSized, Tag};
6
7#[repr(u32)]
13#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum RelocatableHeaderTagPreference {
15    None = 0,
17    Low = 1,
19    High = 2,
21}
22
23#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25#[repr(C, align(8))]
26pub struct RelocatableHeaderTag {
27    header: HeaderTagHeader,
28    min_addr: u32,
30    max_addr: u32,
32    align: u32,
34    preference: RelocatableHeaderTagPreference,
35}
36
37impl RelocatableHeaderTag {
38    #[must_use]
40    pub const fn new(
41        flags: HeaderTagFlag,
42        min_addr: u32,
43        max_addr: u32,
44        align: u32,
45        preference: RelocatableHeaderTagPreference,
46    ) -> Self {
47        let header = HeaderTagHeader::new(
48            HeaderTagType::Relocatable,
49            flags,
50            mem::size_of::<Self>() as u32,
51        );
52        Self {
53            header,
54            min_addr,
55            max_addr,
56            align,
57            preference,
58        }
59    }
60
61    #[must_use]
63    pub const fn typ(&self) -> HeaderTagType {
64        self.header.typ()
65    }
66
67    #[must_use]
69    pub const fn flags(&self) -> HeaderTagFlag {
70        self.header.flags()
71    }
72
73    #[must_use]
75    pub const fn size(&self) -> u32 {
76        self.header.size()
77    }
78
79    #[must_use]
81    pub const fn min_addr(&self) -> u32 {
82        self.min_addr
83    }
84
85    #[must_use]
87    pub const fn max_addr(&self) -> u32 {
88        self.max_addr
89    }
90
91    #[must_use]
93    pub const fn align(&self) -> u32 {
94        self.align
95    }
96
97    #[must_use]
99    pub const fn preference(&self) -> RelocatableHeaderTagPreference {
100        self.preference
101    }
102}
103
104impl Debug for RelocatableHeaderTag {
105    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
106        f.debug_struct("RelocatableHeaderTag")
107            .field("type", &self.typ())
108            .field("flags", &self.flags())
109            .field("size", &self.size())
110            .field("min_addr", &self.min_addr)
112            .field("max_addr", &self.max_addr)
113            .field("align", &self.align)
114            .field("preference", &self.preference)
115            .finish()
116    }
117}
118
119impl MaybeDynSized for RelocatableHeaderTag {
120    type Header = HeaderTagHeader;
121
122    const BASE_SIZE: usize = mem::size_of::<Self>();
123
124    fn dst_len(_header: &Self::Header) -> Self::Metadata {}
125}
126
127impl Tag for RelocatableHeaderTag {
128    type IDType = HeaderTagType;
129    const ID: HeaderTagType = HeaderTagType::Relocatable;
130}
131
132#[cfg(test)]
133mod tests {
134    use crate::RelocatableHeaderTag;
135
136    #[test]
137    fn test_assert_size() {
138        assert_eq!(
139            core::mem::size_of::<RelocatableHeaderTag>(),
140            2 + 2 + 4 + 4 + 4 + 4 + 4
141        );
142    }
143}