Skip to main content

multiboot2_header/
address.rs

1use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType};
2use multiboot2_common::{MaybeDynSized, Tag};
3
4/// Binary address information for non-ELF images.
5///
6/// This information does not need to be provided if the kernel image is in ELF
7/// format, but it must be provided if the image is in a.out format or in some
8/// other format. Required for legacy boot (BIOS).
9/// Determines load addresses.
10#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(C, align(8))]
12pub struct AddressHeaderTag {
13    header: HeaderTagHeader,
14    /// Address corresponding to the beginning of the Multiboot2 header.
15    ///
16    /// This is the physical memory location at which the magic value is
17    /// supposed to be loaded. It synchronizes the mapping between OS image
18    /// offsets and physical memory addresses.
19    header_addr: u32,
20    /// Physical address of the beginning of the text segment.
21    ///
22    /// The offset in the OS image file at which to start loading is the offset
23    /// at which the header was found, minus `header_addr - load_addr`.
24    /// `load_addr` must be less than or equal to `header_addr`.
25    ///
26    /// The special value -1 means that the file must be loaded from its
27    /// beginning.
28    load_addr: u32,
29    /// Physical address of the end of the data segment.
30    ///
31    /// `load_end_addr - load_addr` specifies how much data to load. This
32    /// implies that the text and data segments must be consecutive in the OS
33    /// image, as they are in existing a.out executable formats. If this field
34    /// is zero, the bootloader assumes that the text and data segments occupy
35    /// the whole OS image file.
36    load_end_addr: u32,
37    /// Physical address of the end of the BSS segment.
38    ///
39    /// The bootloader initializes this area to zero and reserves its memory
40    /// to avoid placing boot modules and other operating-system data there. If
41    /// this field is zero, the bootloader assumes that no BSS segment exists.
42    bss_end_addr: u32,
43}
44
45impl AddressHeaderTag {
46    /// Constructs a new tag.
47    #[must_use]
48    pub const fn new(
49        flags: HeaderTagFlag,
50        header_addr: u32,
51        load_addr: u32,
52        load_end_addr: u32,
53        bss_end_addr: u32,
54    ) -> Self {
55        let header = HeaderTagHeader::new(HeaderTagType::Address, flags, size_of::<Self>() as u32);
56        Self {
57            header,
58            header_addr,
59            load_addr,
60            load_end_addr,
61            bss_end_addr,
62        }
63    }
64
65    /// Returns the [`HeaderTagType`].
66    #[must_use]
67    pub const fn typ(&self) -> HeaderTagType {
68        self.header.typ()
69    }
70
71    /// Returns the [`HeaderTagFlag`]s.
72    #[must_use]
73    pub const fn flags(&self) -> HeaderTagFlag {
74        self.header.flags()
75    }
76
77    /// Returns the size.
78    #[must_use]
79    pub const fn size(&self) -> u32 {
80        self.header.size()
81    }
82
83    /// Returns the header address.
84    #[must_use]
85    pub const fn header_addr(&self) -> u32 {
86        self.header_addr
87    }
88
89    /// Returns the load begin address.
90    #[must_use]
91    pub const fn load_addr(&self) -> u32 {
92        self.load_addr
93    }
94
95    /// Returns the load end address.
96    #[must_use]
97    pub const fn load_end_addr(&self) -> u32 {
98        self.load_end_addr
99    }
100
101    /// Returns the bss end address.
102    #[must_use]
103    pub const fn bss_end_addr(&self) -> u32 {
104        self.bss_end_addr
105    }
106}
107
108impl MaybeDynSized for AddressHeaderTag {
109    type Header = HeaderTagHeader;
110
111    const BASE_SIZE: usize = size_of::<Self>();
112}
113
114impl Tag for AddressHeaderTag {
115    type IDType = HeaderTagType;
116    const ID: HeaderTagType = HeaderTagType::Address;
117}
118
119#[cfg(test)]
120mod tests {
121    use crate::AddressHeaderTag;
122
123    #[test]
124    fn test_assert_size() {
125        assert_eq!(size_of::<AddressHeaderTag>(), 2 + 2 + 4 + 4 + 4 + 4 + 4);
126    }
127}