1#![allow(dead_code)]
8
9use super::{
10 frame_allocator::ReservedRegion, FrameNumber, MemoryRegion, FRAME_ALLOCATOR, FRAME_SIZE,
11};
12use crate::error::KernelError;
13
14#[cfg(feature = "alloc")]
15extern crate alloc;
16
17#[cfg(feature = "alloc")]
18use alloc::vec::Vec;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum MemoryRegionType {
23 Usable,
25 Reserved,
27 AcpiReclaimable,
29 AcpiNvs,
31 BadMemory,
33 KernelAndModules,
35 BootloaderReclaimable,
37 Framebuffer,
39 Unknown(u32),
41}
42
43#[derive(Debug, Clone, Copy)]
45pub struct BootloaderMemoryRegion {
46 pub start: u64,
47 pub size: u64,
48 pub region_type: MemoryRegionType,
49}
50
51impl BootloaderMemoryRegion {
52 pub const fn new(start: u64, size: u64, region_type: MemoryRegionType) -> Self {
54 Self {
55 start,
56 size,
57 region_type,
58 }
59 }
60
61 pub const fn is_usable(&self) -> bool {
63 matches!(self.region_type, MemoryRegionType::Usable)
64 }
65
66 pub const fn to_memory_region(self) -> MemoryRegion {
68 MemoryRegion {
69 start: self.start,
70 size: self.size,
71 usable: self.is_usable(),
72 }
73 }
74}
75
76#[cfg(target_arch = "x86_64")]
78pub fn parse_e820_map(entries: &[(u64, u64, u32)]) -> Vec<BootloaderMemoryRegion> {
79 let mut regions = Vec::with_capacity(entries.len());
80
81 for &(base, length, typ) in entries {
82 let region_type = match typ {
83 1 => MemoryRegionType::Usable,
84 2 => MemoryRegionType::Reserved,
85 3 => MemoryRegionType::AcpiReclaimable,
86 4 => MemoryRegionType::AcpiNvs,
87 5 => MemoryRegionType::BadMemory,
88 _ => MemoryRegionType::Unknown(typ),
89 };
90
91 regions.push(BootloaderMemoryRegion::new(base, length, region_type));
92 }
93
94 regions
95}
96
97pub fn parse_uefi_map(descriptors: &[UefiMemoryDescriptor]) -> Vec<BootloaderMemoryRegion> {
99 let mut regions = Vec::with_capacity(descriptors.len());
100
101 for desc in descriptors {
102 let region_type = match desc.typ {
103 0..=2 => MemoryRegionType::Reserved,
104 3 => MemoryRegionType::BootloaderReclaimable,
105 4 => MemoryRegionType::BootloaderReclaimable,
106 7 => MemoryRegionType::Usable,
107 9 => MemoryRegionType::AcpiReclaimable,
108 10 => MemoryRegionType::AcpiNvs,
109 11 => MemoryRegionType::Reserved,
110 _ => MemoryRegionType::Unknown(desc.typ),
111 };
112
113 regions.push(BootloaderMemoryRegion::new(
114 desc.phys_start,
115 desc.num_pages * 4096, region_type,
117 ));
118 }
119
120 regions
121}
122
123#[repr(C)]
125pub struct UefiMemoryDescriptor {
126 pub typ: u32,
127 pub phys_start: u64,
128 pub virt_start: u64,
129 pub num_pages: u64,
130 pub attr: u64,
131}
132
133pub fn process_memory_map(regions: &[BootloaderMemoryRegion]) -> Result<(), KernelError> {
135 println!("[BOOT] Processing bootloader memory map...");
136
137 let mut total_memory = 0u64;
138 let mut usable_memory = 0u64;
139 let mut reserved_count = 0;
140
141 for region in regions {
143 total_memory += region.size;
144
145 match region.region_type {
146 MemoryRegionType::Reserved
147 | MemoryRegionType::AcpiNvs
148 | MemoryRegionType::BadMemory
149 | MemoryRegionType::KernelAndModules
150 | MemoryRegionType::Framebuffer => {
151 let start_frame = region.start / FRAME_SIZE as u64;
153 let end_frame = (region.start + region.size).div_ceil(FRAME_SIZE as u64);
154
155 let description = match region.region_type {
156 MemoryRegionType::Reserved => "Reserved",
157 MemoryRegionType::AcpiNvs => "ACPI NVS",
158 MemoryRegionType::BadMemory => "Bad Memory",
159 MemoryRegionType::KernelAndModules => "Kernel/Modules",
160 MemoryRegionType::Framebuffer => "Framebuffer",
161 _ => "Reserved",
162 };
163
164 let reserved = ReservedRegion {
165 start: FrameNumber::new(start_frame),
166 end: FrameNumber::new(end_frame),
167 description,
168 };
169
170 FRAME_ALLOCATOR
171 .lock()
172 .add_reserved_region(reserved)
173 .map_err(|_| KernelError::ResourceExhausted {
174 resource: "reserved memory regions",
175 })?;
176
177 reserved_count += 1;
178 }
179 _ => {}
180 }
181 }
182
183 let mut allocator = FRAME_ALLOCATOR.lock();
185 let mut region_count = 0;
186
187 for region in regions {
188 if region.is_usable() {
189 usable_memory += region.size;
190
191 let start_frame = region.start / FRAME_SIZE as u64;
192 let frame_count = region.size as usize / FRAME_SIZE;
193
194 if frame_count < 16 {
196 continue;
197 }
198
199 let numa_node = region_count % 8;
201
202 if let Err(_e) =
203 allocator.init_numa_node(numa_node, FrameNumber::new(start_frame), frame_count)
204 {
205 println!(
206 "[BOOT] Warning: Failed to add memory region at 0x{:x}",
207 region.start
208 );
209 } else {
210 println!(
211 "[BOOT] Added {} MB at 0x{:x} (NUMA node {})",
212 region.size / (1024 * 1024),
213 region.start,
214 numa_node
215 );
216 region_count += 1;
217 }
218 }
219 }
220
221 drop(allocator);
222
223 #[cfg(target_arch = "x86_64")]
224 println!(
225 "[BOOT] Memory map processed: {} MB total, {} MB usable, {} reserved regions",
226 total_memory / (1024 * 1024),
227 usable_memory / (1024 * 1024),
228 reserved_count
229 );
230
231 #[cfg(not(target_arch = "x86_64"))]
232 {
233 let _ = total_memory;
234 let _ = usable_memory;
235 let _ = reserved_count;
236 println!("[BOOT] Memory map processed");
237 }
238
239 Ok(())
240}
241
242pub fn reserve_standard_regions() -> Result<(), KernelError> {
244 let allocator = FRAME_ALLOCATOR.lock();
245
246 let bios_region = ReservedRegion {
248 start: FrameNumber::new(0),
249 end: FrameNumber::new(256),
250 description: "BIOS/Real mode",
251 };
252 allocator
253 .add_reserved_region(bios_region)
254 .map_err(|_| KernelError::ResourceExhausted {
255 resource: "reserved memory regions",
256 })?;
257
258 let video_region = ReservedRegion {
260 start: FrameNumber::new(0xA0),
261 end: FrameNumber::new(0x100),
262 description: "Video memory",
263 };
264 allocator
265 .add_reserved_region(video_region)
266 .map_err(|_| KernelError::ResourceExhausted {
267 resource: "reserved memory regions",
268 })?;
269
270 #[cfg(target_arch = "x86_64")]
272 {
273 let apic_frame = 0xFEE00000 / FRAME_SIZE as u64;
274 let apic_region = ReservedRegion {
275 start: FrameNumber::new(apic_frame),
276 end: FrameNumber::new(apic_frame + 1),
277 description: "Local APIC",
278 };
279 allocator
280 .add_reserved_region(apic_region)
281 .map_err(|_| KernelError::ResourceExhausted {
282 resource: "reserved memory regions",
283 })?;
284 }
285
286 Ok(())
287}