Skip to main content

multiboot2/
efi.rs

1//! All tags related to (U)EFI with the exception of EFI memory tags:
2//!
3//! - [`EFISdt32Tag`]
4//! - [`EFISdt64Tag`]
5//! - [`EFIImageHandle32Tag`]
6//! - [`EFIImageHandle64Tag`]
7//! - [`EFIBootServicesNotExitedTag`]
8
9use crate::TagType;
10use crate::tag::TagHeader;
11use multiboot2_common::{MaybeDynSized, Tag};
12
13/// EFI system table in 32 bit mode tag.
14#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[repr(C, align(8))]
16pub struct EFISdt32Tag {
17    header: TagHeader,
18    pointer: u32,
19}
20
21impl EFISdt32Tag {
22    const BASE_SIZE: usize = size_of::<TagHeader>() + size_of::<u32>();
23
24    /// Create a new tag to pass the EFI32 System Table pointer.
25    #[must_use]
26    pub fn new(pointer: u32) -> Self {
27        Self {
28            header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
29            pointer,
30        }
31    }
32
33    /// The physical address of a i386 EFI system table.
34    #[must_use]
35    pub const fn sdt_address(&self) -> usize {
36        self.pointer as usize
37    }
38}
39
40impl MaybeDynSized for EFISdt32Tag {
41    type Header = TagHeader;
42
43    const BASE_SIZE: usize = size_of::<Self>();
44}
45
46impl Tag for EFISdt32Tag {
47    type IDType = TagType;
48
49    const ID: TagType = TagType::Efi32;
50}
51
52/// EFI system table in 64 bit mode tag.
53#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
54#[repr(C, align(8))]
55pub struct EFISdt64Tag {
56    header: TagHeader,
57    pointer: u64,
58}
59
60impl EFISdt64Tag {
61    /// Create a new tag to pass the EFI64 System Table pointer.
62    #[must_use]
63    pub fn new(pointer: u64) -> Self {
64        Self {
65            header: TagHeader::new(Self::ID, size_of::<Self>().try_into().unwrap()),
66            pointer,
67        }
68    }
69
70    /// The physical address of a x86_64 EFI system table.
71    #[must_use]
72    pub const fn sdt_address(&self) -> usize {
73        self.pointer as usize
74    }
75}
76
77impl MaybeDynSized for EFISdt64Tag {
78    type Header = TagHeader;
79
80    const BASE_SIZE: usize = size_of::<Self>();
81}
82
83impl Tag for EFISdt64Tag {
84    type IDType = TagType;
85
86    const ID: TagType = TagType::Efi64;
87}
88
89/// Tag that contains the pointer to the boot loader's UEFI image handle
90/// (32-bit).
91#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
92#[repr(C, align(8))]
93pub struct EFIImageHandle32Tag {
94    header: TagHeader,
95    pointer: u32,
96}
97
98impl EFIImageHandle32Tag {
99    const BASE_SIZE: usize = size_of::<TagHeader>() + size_of::<u32>();
100
101    /// Constructs a new tag.
102    #[must_use]
103    pub fn new(pointer: u32) -> Self {
104        Self {
105            header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
106            pointer,
107        }
108    }
109
110    /// Returns the physical address of the EFI image handle.
111    #[must_use]
112    pub const fn image_handle(&self) -> usize {
113        self.pointer as usize
114    }
115}
116
117impl MaybeDynSized for EFIImageHandle32Tag {
118    type Header = TagHeader;
119
120    const BASE_SIZE: usize = size_of::<Self>();
121}
122
123impl Tag for EFIImageHandle32Tag {
124    type IDType = TagType;
125
126    const ID: TagType = TagType::Efi32Ih;
127}
128
129/// Tag that contains the pointer to the boot loader's UEFI image handle
130/// (64-bit).
131#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
132#[repr(C, align(8))]
133pub struct EFIImageHandle64Tag {
134    header: TagHeader,
135    pointer: u64,
136}
137
138impl EFIImageHandle64Tag {
139    /// Constructs a new tag.
140    #[must_use]
141    pub fn new(pointer: u64) -> Self {
142        Self {
143            header: TagHeader::new(Self::ID, size_of::<Self>().try_into().unwrap()),
144            pointer,
145        }
146    }
147
148    /// Returns the physical address of the EFI image handle.
149    #[must_use]
150    pub const fn image_handle(&self) -> usize {
151        self.pointer as usize
152    }
153}
154
155impl MaybeDynSized for EFIImageHandle64Tag {
156    type Header = TagHeader;
157
158    const BASE_SIZE: usize = size_of::<Self>();
159}
160
161impl Tag for EFIImageHandle64Tag {
162    type IDType = TagType;
163
164    const ID: TagType = TagType::Efi64Ih;
165}
166
167/// EFI ExitBootServices was not called tag. This tag has no payload and is
168/// just a marker.
169#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
170#[repr(C, align(8))]
171pub struct EFIBootServicesNotExitedTag {
172    header: TagHeader,
173}
174
175impl EFIBootServicesNotExitedTag {
176    /// Constructs a new tag.
177    #[must_use]
178    pub fn new() -> Self {
179        Self::default()
180    }
181}
182
183impl Default for EFIBootServicesNotExitedTag {
184    fn default() -> Self {
185        Self {
186            header: TagHeader::new(Self::ID, size_of::<Self>().try_into().unwrap()),
187        }
188    }
189}
190
191impl MaybeDynSized for EFIBootServicesNotExitedTag {
192    type Header = TagHeader;
193
194    const BASE_SIZE: usize = size_of::<Self>();
195}
196
197impl Tag for EFIBootServicesNotExitedTag {
198    type IDType = TagType;
199
200    const ID: TagType = TagType::EfiBs;
201}
202
203#[cfg(all(test, feature = "builder"))]
204mod tests {
205    use super::{EFIImageHandle32Tag, EFIImageHandle64Tag, EFISdt32Tag, EFISdt64Tag};
206    use crate::{EFIMemoryDesc, EFIMemoryMapTag};
207    use uefi_raw::table::boot::{MemoryAttribute, MemoryType};
208
209    const ADDR: usize = 0xABCDEF;
210
211    #[test]
212    fn test_build_eftsdt32() {
213        let tag = EFISdt32Tag::new(ADDR.try_into().unwrap());
214        assert_eq!(tag.sdt_address(), ADDR);
215    }
216
217    #[test]
218    fn test_build_eftsdt64() {
219        let tag = EFISdt64Tag::new(ADDR.try_into().unwrap());
220        assert_eq!(tag.sdt_address(), ADDR);
221    }
222
223    #[test]
224    fn test_build_eftih32() {
225        let tag = EFIImageHandle32Tag::new(ADDR.try_into().unwrap());
226        assert_eq!(tag.image_handle(), ADDR);
227    }
228
229    #[test]
230    fn test_build_eftih64() {
231        let tag = EFIImageHandle64Tag::new(ADDR.try_into().unwrap());
232        assert_eq!(tag.image_handle(), ADDR);
233    }
234
235    #[test]
236    fn test_construct_efi_mmap_tag() {
237        let tag = EFIMemoryMapTag::new_from_descs(&[
238            EFIMemoryDesc {
239                ty: MemoryType::BOOT_SERVICES_CODE,
240                phys_start: 0x1000,
241                virt_start: 0x1000,
242                page_count: 1,
243                att: MemoryAttribute::WRITE_COMBINE,
244            },
245            EFIMemoryDesc {
246                ty: MemoryType::LOADER_DATA,
247                phys_start: 0x2000,
248                virt_start: 0x2000,
249                page_count: 2,
250                att: MemoryAttribute::NON_VOLATILE,
251            },
252        ]);
253        // Test for Miri
254        dbg!(tag);
255    }
256}