strat9_kernel/ostd/
boot.rs1#![deny(unsafe_code)]
11
12extern crate alloc;
13
14use alloc::vec::Vec;
15use core::fmt;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[repr(u32)]
20pub enum MemoryRegionType {
21 Usable = 0,
23 Reserved = 1,
25 AcpiReclaimable = 2,
27 AcpiNvs = 3,
29 Bad = 4,
31 Unknown = 0xFF,
33}
34
35impl From<u32> for MemoryRegionType {
36 fn from(value: u32) -> Self {
38 match value {
39 0 => Self::Usable,
40 1 => Self::Reserved,
41 2 => Self::AcpiReclaimable,
42 3 => Self::AcpiNvs,
43 4 => Self::Bad,
44 _ => Self::Unknown,
45 }
46 }
47}
48
49#[derive(Debug, Clone, Copy)]
51#[repr(C)]
52pub struct MemoryRegion {
53 pub base: u64,
55 pub size: u64,
57 pub region_type: MemoryRegionType,
59}
60
61impl MemoryRegion {
62 pub const fn new(base: u64, size: u64, region_type: MemoryRegionType) -> Self {
64 Self {
65 base,
66 size,
67 region_type,
68 }
69 }
70
71 pub const fn end(&self) -> u64 {
73 self.base.wrapping_add(self.size)
74 }
75
76 pub const fn is_usable(&self) -> bool {
78 matches!(self.region_type, MemoryRegionType::Usable)
79 }
80
81 pub const fn is_acpi_reclaimable(&self) -> bool {
83 matches!(self.region_type, MemoryRegionType::AcpiReclaimable)
84 }
85
86 pub const fn is_acpi_nvs(&self) -> bool {
88 matches!(self.region_type, MemoryRegionType::AcpiNvs)
89 }
90}
91
92#[derive(Debug, Clone)]
94pub struct BootModule {
95 pub base: u64,
97 pub size: u64,
99 pub name: alloc::string::String,
101}
102
103impl BootModule {
104 pub fn new(base: u64, size: u64, name: alloc::string::String) -> Self {
106 Self { base, size, name }
107 }
108
109 pub fn end(&self) -> u64 {
111 self.base.wrapping_add(self.size)
112 }
113}
114
115#[derive(Debug, Clone)]
117pub struct BootInfo {
118 pub memory_map: Vec<MemoryRegion>,
120 pub hhdm_offset: u64,
122 pub acpi_rsdp: u64,
124 pub modules: Vec<BootModule>,
126 pub cmdline: alloc::string::String,
128}
129
130impl BootInfo {
131 pub fn new(
133 memory_map: Vec<MemoryRegion>,
134 hhdm_offset: u64,
135 acpi_rsdp: u64,
136 modules: Vec<BootModule>,
137 cmdline: alloc::string::String,
138 ) -> Self {
139 Self {
140 memory_map,
141 hhdm_offset,
142 acpi_rsdp,
143 modules,
144 cmdline,
145 }
146 }
147
148 pub fn usable_regions(&self) -> impl Iterator<Item = &MemoryRegion> {
150 self.memory_map.iter().filter(|r| r.is_usable())
151 }
152
153 pub fn total_usable_ram(&self) -> u64 {
155 self.usable_regions().map(|r| r.size).sum()
156 }
157
158 pub fn total_physical_memory(&self) -> u64 {
160 self.memory_map.iter().map(|r| r.size).sum()
161 }
162
163 pub fn find_module(&self, name: &str) -> Option<&BootModule> {
165 self.modules.iter().find(|m| m.name == name)
166 }
167}
168
169impl fmt::Display for BootInfo {
170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 writeln!(f, "Boot Information:")?;
173 writeln!(f, " HHDM Offset: 0x{:x}", self.hhdm_offset)?;
174 writeln!(f, " ACPI RSDP: 0x{:x}", self.acpi_rsdp)?;
175 writeln!(f, " Memory Regions:")?;
176 for region in &self.memory_map {
177 writeln!(
178 f,
179 " 0x{:016x}-0x{:016x}: {:?} ({} KB)",
180 region.base,
181 region.end(),
182 region.region_type,
183 region.size / 1024
184 )?;
185 }
186 writeln!(
187 f,
188 " Total Usable RAM: {} MB",
189 self.total_usable_ram() / (1024 * 1024)
190 )?;
191 writeln!(f, " Modules: {}", self.modules.len())?;
192 for module in &self.modules {
193 writeln!(
194 f,
195 " {}: 0x{:x} ({} bytes)",
196 module.name, module.base, module.size
197 )?;
198 }
199 if !self.cmdline.is_empty() {
200 writeln!(f, " Command Line: {}", self.cmdline)?;
201 }
202 Ok(())
203 }
204}