hermit_entry/boot_info/
mod.rs

1//! Creating and reading [`RawBootInfo`] from [`Entry`](crate::Entry).
2//!
3//! Loaders assemble [`BootInfo`] and convert it into a [`RawBootInfo`] to pass it to the kernel.
4//!
5//! The kernel copies [`BootInfo`] from [`RawBootInfo`] to work with the values.
6
7#[cfg(feature = "loader")]
8mod loader;
9
10#[cfg(feature = "kernel")]
11mod kernel;
12
13use core::num::{NonZeroU32, NonZeroU64};
14use core::ops::Range;
15
16use time::OffsetDateTime;
17
18/// Serial I/O port.
19#[cfg(target_arch = "x86_64")]
20pub type SerialPortBase = core::num::NonZeroU16;
21
22/// Serial port base address
23#[cfg(target_arch = "aarch64")]
24pub type SerialPortBase = core::num::NonZeroU64;
25
26/// Serial port base address
27#[cfg(target_arch = "riscv64")]
28pub type SerialPortBase = core::num::NonZeroU64;
29
30/// Device tree address
31pub type DeviceTreeAddress = core::num::NonZeroU64;
32
33/// Boot information.
34///
35/// This struct is built by the loader and consumed by the kernel.
36/// It contains information on how the kernel image was loaded as well as
37/// additional hardware and loader specific information.
38#[derive(Debug)]
39pub struct BootInfo {
40    /// Hardware information.
41    pub hardware_info: HardwareInfo,
42
43    /// Load information.
44    pub load_info: LoadInfo,
45
46    /// Platform information.
47    pub platform_info: PlatformInfo,
48}
49
50/// Hardware information.
51#[derive(Debug)]
52pub struct HardwareInfo {
53    /// The range of all possible physical memory addresses.
54    pub phys_addr_range: Range<u64>,
55
56    /// Serial port base address.
57    pub serial_port_base: Option<SerialPortBase>,
58
59    /// Address of the device tree
60    pub device_tree: Option<DeviceTreeAddress>,
61}
62
63/// Load information.
64#[derive(Debug)]
65pub struct LoadInfo {
66    /// The virtual address range of the loaded kernel image.
67    pub kernel_image_addr_range: Range<u64>,
68
69    /// Kernel image TLS information.
70    pub tls_info: Option<TlsInfo>,
71}
72
73/// Platform information.
74///
75/// This struct holds platform and loader specific information.
76#[derive(Debug)]
77pub enum PlatformInfo {
78    /// Multiboot.
79    #[cfg(target_arch = "x86_64")]
80    Multiboot {
81        /// Command line passed to the kernel.
82        command_line: Option<&'static str>,
83
84        /// Multiboot boot information address.
85        multiboot_info_addr: core::num::NonZeroU64,
86    },
87    /// Direct Linux Boot.
88    #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
89    LinuxBoot,
90    /// Uhyve.
91    Uhyve {
92        /// PCI support.
93        has_pci: bool,
94
95        /// Total number of CPUs available.
96        num_cpus: NonZeroU64,
97
98        /// CPU frequency in kHz.
99        cpu_freq: Option<NonZeroU32>,
100
101        /// Boot time.
102        boot_time: OffsetDateTime,
103    },
104    /// Linux Boot Parameters.
105    LinuxBootParams {
106        /// Command line passed to the kernel.
107        command_line: Option<&'static str>,
108
109        /// Address to Linux boot parameters.
110        boot_params_addr: core::num::NonZeroU64,
111    },
112    /// FDT.
113    ///
114    /// This is a transitional platform for migrating to FDTs.
115    /// The real platform information is stored in [`HardwareInfo::device_tree`].
116    Fdt,
117}
118
119/// Thread local storage (TLS) image information.
120#[repr(C)]
121#[derive(Clone, Copy, Debug)]
122pub struct TlsInfo {
123    /// The start address of the TLS image.
124    pub start: u64,
125
126    /// `filesz` of the TLS program header.
127    pub filesz: u64,
128
129    /// `memsz` of the TLS program header.
130    pub memsz: u64,
131
132    /// `align` of the TLS program header.
133    pub align: u64,
134}
135
136/// The raw boot information struct.
137///
138/// This is kept separate from [`BootInfo`] to make non-breaking API evolution possible.
139#[derive(Clone, Copy, Debug)]
140#[repr(C)]
141pub struct RawBootInfo {
142    hardware_info: RawHardwareInfo,
143    load_info: RawLoadInfo,
144    platform_info: RawPlatformInfo,
145}
146
147#[derive(Clone, Copy, Debug)]
148#[repr(C)]
149struct RawHardwareInfo {
150    phys_addr_start: u64,
151    phys_addr_end: u64,
152    serial_port_base: Option<SerialPortBase>,
153    device_tree: Option<DeviceTreeAddress>,
154}
155
156#[derive(Clone, Copy, Debug)]
157#[repr(C)]
158struct RawLoadInfo {
159    kernel_image_addr_start: u64,
160    kernel_image_addr_end: u64,
161    tls_info: TlsInfo,
162}
163
164#[derive(Clone, Copy, Debug)]
165#[cfg_attr(target_arch = "x86_64", repr(C, align(8)))]
166#[cfg_attr(not(target_arch = "x86_64"), repr(transparent))]
167struct Align8<T>(pub T);
168
169impl<T> From<T> for Align8<T> {
170    fn from(value: T) -> Self {
171        Self(value)
172    }
173}
174
175#[cfg_attr(not(all(feature = "loader", feature = "kernel")), expect(dead_code))]
176#[derive(Clone, Copy, Debug)]
177#[repr(C)]
178enum RawPlatformInfo {
179    #[cfg(target_arch = "x86_64")]
180    Multiboot {
181        command_line_data: *const u8,
182        command_line_len: u64,
183        multiboot_info_addr: core::num::NonZeroU64,
184    },
185    #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
186    LinuxBoot,
187    Uhyve {
188        has_pci: bool,
189        num_cpus: NonZeroU64,
190        cpu_freq: Option<NonZeroU32>,
191        boot_time: Align8<[u8; 16]>,
192    },
193    LinuxBootParams {
194        command_line_data: *const u8,
195        command_line_len: u64,
196        boot_params_addr: core::num::NonZeroU64,
197    },
198    Fdt,
199}