Skip to main content

multiboot2_header/
relocatable.rs

1use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType};
2use core::fmt;
3use core::fmt::{Debug, Formatter};
4use multiboot2_common::{MaybeDynSized, Tag};
5
6/// It contains load address placement suggestion for bootloader.
7///
8/// Bootloader should follow it. ‘0’ means none, ‘1’ means load image at lowest
9/// possible address but not lower than min addr and ‘2’ means load image at
10/// highest possible address but not higher than max addr.
11#[repr(u32)]
12#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum RelocatableHeaderTagPreference {
14    /// Let boot loader decide.
15    None = 0,
16    /// Locate at lower end of possible address space.
17    Low = 1,
18    /// Locate at higher end of possible address space.
19    High = 2,
20}
21
22/// This tag indicates that the image is relocatable.
23#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[repr(C, align(8))]
25pub struct RelocatableHeaderTag {
26    header: HeaderTagHeader,
27    /// Lowest possible physical address at which image should be loaded. The bootloader cannot load any part of image below this address
28    min_addr: u32,
29    /// Highest possible physical address at which loaded image should end. The bootloader cannot load any part of image above this address.
30    max_addr: u32,
31    /// Image alignment in memory, e.g. 4096.
32    align: u32,
33    preference: RelocatableHeaderTagPreference,
34}
35
36impl RelocatableHeaderTag {
37    /// Constructs a new tag.
38    #[must_use]
39    pub const fn new(
40        flags: HeaderTagFlag,
41        min_addr: u32,
42        max_addr: u32,
43        align: u32,
44        preference: RelocatableHeaderTagPreference,
45    ) -> Self {
46        let header =
47            HeaderTagHeader::new(HeaderTagType::Relocatable, flags, size_of::<Self>() as u32);
48        Self {
49            header,
50            min_addr,
51            max_addr,
52            align,
53            preference,
54        }
55    }
56
57    /// Returns the [`HeaderTagType`].
58    #[must_use]
59    pub const fn typ(&self) -> HeaderTagType {
60        self.header.typ()
61    }
62
63    /// Returns the [`HeaderTagFlag`]s.
64    #[must_use]
65    pub const fn flags(&self) -> HeaderTagFlag {
66        self.header.flags()
67    }
68
69    /// Returns the size.
70    #[must_use]
71    pub const fn size(&self) -> u32 {
72        self.header.size()
73    }
74
75    /// Return the minimum address.
76    #[must_use]
77    pub const fn min_addr(&self) -> u32 {
78        self.min_addr
79    }
80
81    /// Return the maximum address.
82    #[must_use]
83    pub const fn max_addr(&self) -> u32 {
84        self.max_addr
85    }
86
87    /// Return the alignment.
88    #[must_use]
89    pub const fn align(&self) -> u32 {
90        self.align
91    }
92
93    /// Return the preference.
94    #[must_use]
95    pub const fn preference(&self) -> RelocatableHeaderTagPreference {
96        self.preference
97    }
98}
99
100impl Debug for RelocatableHeaderTag {
101    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
102        f.debug_struct("RelocatableHeaderTag")
103            .field("type", &self.typ())
104            .field("flags", &self.flags())
105            .field("size", &self.size())
106            // trick to print this as hexadecimal pointer
107            .field("min_addr", &self.min_addr)
108            .field("max_addr", &self.max_addr)
109            .field("align", &self.align)
110            .field("preference", &self.preference)
111            .finish()
112    }
113}
114
115impl MaybeDynSized for RelocatableHeaderTag {
116    type Header = HeaderTagHeader;
117
118    const BASE_SIZE: usize = size_of::<Self>();
119}
120
121impl Tag for RelocatableHeaderTag {
122    type IDType = HeaderTagType;
123    const ID: HeaderTagType = HeaderTagType::Relocatable;
124}
125
126#[cfg(test)]
127mod tests {
128    use crate::RelocatableHeaderTag;
129
130    #[test]
131    fn test_assert_size() {
132        assert_eq!(size_of::<RelocatableHeaderTag>(), 2 + 2 + 4 + 4 + 4 + 4 + 4);
133    }
134}