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}