multiboot2_header/
information_request.rs

1use crate::{HeaderTagFlag, HeaderTagHeader};
2use crate::{HeaderTagType, MbiTagTypeId};
3use core::fmt;
4use core::fmt::{Debug, Formatter};
5use core::mem;
6#[cfg(feature = "builder")]
7use multiboot2_common::new_boxed;
8use multiboot2_common::{MaybeDynSized, Tag};
9#[cfg(feature = "builder")]
10use {
11    alloc::boxed::Box,
12    core::{ptr, slice},
13};
14
15/// Specifies what specific tag types the bootloader should provide
16/// inside the mbi.
17#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, ptr_meta::Pointee)]
18#[repr(C, align(8))]
19pub struct InformationRequestHeaderTag {
20    header: HeaderTagHeader,
21    requests: [MbiTagTypeId],
22}
23
24impl InformationRequestHeaderTag {
25    /// Creates a new object.
26    #[cfg(feature = "builder")]
27    #[must_use]
28    pub fn new(flags: HeaderTagFlag, requests: &[MbiTagTypeId]) -> Box<Self> {
29        let header = HeaderTagHeader::new(HeaderTagType::InformationRequest, flags, 0);
30        let requests = unsafe {
31            let ptr = ptr::addr_of!(*requests);
32            slice::from_raw_parts(ptr.cast::<u8>(), mem::size_of_val(requests))
33        };
34        new_boxed(header, &[requests])
35    }
36
37    /// Returns the [`HeaderTagType`].
38    #[must_use]
39    pub const fn typ(&self) -> HeaderTagType {
40        self.header.typ()
41    }
42
43    /// Returns the [`HeaderTagFlag`]s.
44    #[must_use]
45    pub const fn flags(&self) -> HeaderTagFlag {
46        self.header.flags()
47    }
48
49    /// Returns the size.
50    #[must_use]
51    pub const fn size(&self) -> u32 {
52        self.header.size()
53    }
54
55    /// Returns the requests as array
56    #[must_use]
57    pub const fn requests(&self) -> &[MbiTagTypeId] {
58        &self.requests
59    }
60}
61
62impl Debug for InformationRequestHeaderTag {
63    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64        f.debug_struct("InformationRequestHeaderTag")
65            .field("type", &self.typ())
66            .field("flags", &self.flags())
67            .field("size", &self.size())
68            .field("requests", &self.requests())
69            .finish()
70    }
71}
72
73impl MaybeDynSized for InformationRequestHeaderTag {
74    type Header = HeaderTagHeader;
75
76    const BASE_SIZE: usize = mem::size_of::<HeaderTagHeader>();
77
78    fn dst_len(header: &Self::Header) -> Self::Metadata {
79        let dst_size = header.size() as usize - Self::BASE_SIZE;
80        assert_eq!(dst_size % mem::size_of::<MbiTagTypeId>(), 0);
81        dst_size / mem::size_of::<MbiTagTypeId>()
82    }
83}
84
85impl Tag for InformationRequestHeaderTag {
86    type IDType = HeaderTagType;
87    const ID: HeaderTagType = HeaderTagType::InformationRequest;
88}
89
90#[cfg(test)]
91#[cfg(feature = "builder")]
92mod tests {
93    use super::*;
94    use crate::MbiTagType;
95
96    #[test]
97    fn creation() {
98        // Main objective here is to satisfy Miri.
99        let _ir = InformationRequestHeaderTag::new(
100            HeaderTagFlag::Optional,
101            &[
102                MbiTagType::Cmdline.into(),
103                MbiTagType::BootLoaderName.into(),
104                MbiTagType::Module.into(),
105                MbiTagType::BasicMeminfo.into(),
106                MbiTagType::Bootdev.into(),
107                MbiTagType::Mmap.into(),
108                MbiTagType::Vbe.into(),
109                MbiTagType::Framebuffer.into(),
110                MbiTagType::ElfSections.into(),
111                MbiTagType::Apm.into(),
112                MbiTagType::Efi32.into(),
113                MbiTagType::Efi64.into(),
114                MbiTagType::Smbios.into(),
115                MbiTagType::AcpiV1.into(),
116                MbiTagType::AcpiV2.into(),
117                MbiTagType::Network.into(),
118                MbiTagType::EfiMmap.into(),
119                MbiTagType::EfiBs.into(),
120                MbiTagType::Efi32Ih.into(),
121                MbiTagType::Efi64Ih.into(),
122                MbiTagType::LoadBaseAddr.into(),
123                MbiTagType::Custom(0x1337).into(),
124            ],
125        );
126    }
127}