Skip to main content

multiboot2_host/bootinfo/
tag.rs

1use std::io::Write;
2
3use byteorder::{WriteBytesExt, LE};
4use num_enum::IntoPrimitive;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub struct MemMapEntry {
8    pub base_addr: u64,
9    pub length: u64,
10    pub entry_type: u32,
11    // 4 reserved bytes as padding
12}
13
14const MEMMAP_ENTRY_VERSION: u32 = 0;
15const MEMMAP_ENTRY_SIZE: u32 = 24;
16
17#[repr(u32)]
18#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive)]
19pub enum TagType {
20    End = 0,
21    BasicMeminfo = 4,
22    MemMap = 6,
23
24    #[cfg(feature = "hvm")]
25    HybridRuntime = 0xF00DF00D,
26}
27
28#[repr(u32)]
29#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive)]
30pub enum RegionType {
31    Available = 1,
32    AcpiReclaimable = 3,
33    NonVolatile = 4,
34    Defective = 5,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub enum Tag {
39    BasicMeminfo {
40        mem_lower: u32,
41        mem_upper: u32,
42    },
43    MemMap {
44        entries: Vec<MemMapEntry>,
45    },
46    #[cfg(feature = "hvm")]
47    HybridRuntime {
48        total_num_apics: u32,
49        first_hrt_apic_id: u32,
50        have_hrt_ioapic: bool, //4 bytes
51        first_hrt_ioapic_entry: u32,
52        cpu_freq_khz: u64,
53        hrt_flags: u64,
54        max_mem_mapped: u64,
55        first_hrt_gpa: u64,
56        boot_state_gpa: u64,
57        gva_offset: u64,
58        comm_page_gpa: u64,
59        hrt_int_vector: u8,
60        // 7 reserved bytes as padding
61    },
62    End,
63}
64
65impl Tag {
66    pub fn tag_type(&self) -> TagType {
67        match self {
68            Tag::BasicMeminfo { .. } => TagType::BasicMeminfo,
69            Tag::MemMap { .. } => TagType::MemMap,
70            #[cfg(feature = "hvm")]
71            Tag::HybridRuntime { .. } => TagType::HybridRuntime,
72            Tag::End => TagType::End,
73        }
74    }
75
76    pub fn size(&self) -> u32 {
77        let body_size = match self {
78            Tag::BasicMeminfo { .. } => 8,
79            Tag::MemMap { entries } => 8 + entries.len() as u32 * MEMMAP_ENTRY_SIZE,
80            #[cfg(feature = "hvm")]
81            Tag::HybridRuntime { .. } => 80,
82            Tag::End => 0,
83        };
84        body_size + 8
85    }
86
87    pub fn write_to<W: Write>(&self, mut w: W) -> std::io::Result<()> {
88        w.write_u32::<LE>(self.tag_type().into())?;
89        w.write_u32::<LE>(self.size())?;
90
91        match self {
92            Tag::BasicMeminfo {
93                mem_lower,
94                mem_upper,
95            } => {
96                w.write_u32::<LE>(*mem_lower)?;
97                w.write_u32::<LE>(*mem_upper)?;
98            }
99            Tag::MemMap { entries } => {
100                w.write_u32::<LE>(MEMMAP_ENTRY_SIZE)?;
101                w.write_u32::<LE>(MEMMAP_ENTRY_VERSION)?;
102                for entry in entries {
103                    w.write_u64::<LE>(entry.base_addr)?;
104                    w.write_u64::<LE>(entry.length)?;
105                    w.write_u32::<LE>(entry.entry_type)?;
106                    w.write_u32::<LE>(0)?; // reserved (padding)
107                }
108            }
109            #[cfg(feature = "hvm")]
110            Tag::HybridRuntime {
111                total_num_apics,
112                first_hrt_apic_id,
113                have_hrt_ioapic,
114                first_hrt_ioapic_entry,
115                cpu_freq_khz,
116                hrt_flags,
117                max_mem_mapped,
118                first_hrt_gpa,
119                boot_state_gpa,
120                gva_offset,
121                comm_page_gpa,
122                hrt_int_vector,
123            } => {
124                for x in &[
125                    *total_num_apics,
126                    *first_hrt_apic_id,
127                    *have_hrt_ioapic as u32,
128                    *first_hrt_ioapic_entry,
129                ] {
130                    w.write_u32::<LE>(*x)?;
131                }
132                for x in &[
133                    *cpu_freq_khz,
134                    *hrt_flags,
135                    *max_mem_mapped,
136                    *first_hrt_gpa,
137                    *boot_state_gpa,
138                    *gva_offset,
139                    *comm_page_gpa,
140                ] {
141                    w.write_u64::<LE>(*x)?;
142                }
143                w.write_u8(*hrt_int_vector)?;
144                w.write(&[0u8; 7])?;
145            }
146            Tag::End => {}
147        }
148        Ok(())
149    }
150}