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}