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
45const _: () = assert!(size_of::<AddressHeaderTag>() == 2 + 2 + 4 + 4 + 4 + 4 + 4);
46
47impl AddressHeaderTag {
48    /// Constructs a new tag.
49    #[must_use]
50    pub const fn new(
51        flags: HeaderTagFlag,
52        header_addr: u32,
53        load_addr: u32,
54        load_end_addr: u32,
55        bss_end_addr: u32,
56    ) -> Self {
57        let header = HeaderTagHeader::new(HeaderTagType::Address, flags, size_of::<Self>() as u32);
58        Self {
59            header,
60            header_addr,
61            load_addr,
62            load_end_addr,
63            bss_end_addr,
64        }
65    }
66
67    /// Returns the [`HeaderTagType`].
68    #[must_use]
69    pub const fn typ(&self) -> HeaderTagType {
70        self.header.typ()
71    }
72
73    /// Returns the [`HeaderTagFlag`]s.
74    #[must_use]
75    pub const fn flags(&self) -> HeaderTagFlag {
76        self.header.flags()
77    }
78
79    /// Returns the size.
80    #[must_use]
81    pub const fn size(&self) -> u32 {
82        self.header.size()
83    }
84
85    /// Returns the header address.
86    #[must_use]
87    pub const fn header_addr(&self) -> u32 {
88        self.header_addr
89    }
90
91    /// Returns the load begin address.
92    #[must_use]
93    pub const fn load_addr(&self) -> u32 {
94        self.load_addr
95    }
96
97    /// Returns the load end address.
98    #[must_use]
99    pub const fn load_end_addr(&self) -> u32 {
100        self.load_end_addr
101    }
102
103    /// Returns the bss end address.
104    #[must_use]
105    pub const fn bss_end_addr(&self) -> u32 {
106        self.bss_end_addr
107    }
108}
109
110// SAFETY: The tag is repr(C) with the header as first field, any bit
111// pattern is valid, and `BASE_SIZE`/`dst_len` match the ABI.
112unsafe impl MaybeDynSized for AddressHeaderTag {
113    type Header = HeaderTagHeader;
114
115    const BASE_SIZE: usize = size_of::<Self>();
116}
117
118impl Tag for AddressHeaderTag {
119    type IDType = HeaderTagType;
120    const ID: HeaderTagType = HeaderTagType::Address;
121}