1 use core::mem::size_of; 2 3 use fdt::{ 4 node::{FdtNode, NodeProperty}, 5 Fdt, 6 }; 7 use system_error::SystemError; 8 9 use crate::{ 10 init::boot_params, 11 libs::rwlock::RwLock, 12 mm::{memblock::mem_block_manager, PhysAddr}, 13 }; 14 15 #[inline(always)] 16 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver { 17 &OpenFirmwareFdtDriver 18 } 19 20 static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new()); 21 22 #[derive(Debug)] 23 struct FdtGlobalData { 24 /// FDT根节点下的`size-cells`属性值 25 root_size_cells: u32, 26 27 /// FDT根节点下的`address-cells`属性值 28 root_addr_cells: u32, 29 30 chosen_node_name: Option<&'static str>, 31 } 32 33 impl FdtGlobalData { 34 pub const fn new() -> Self { 35 Self { 36 root_size_cells: 1, 37 root_addr_cells: 1, 38 chosen_node_name: None, 39 } 40 } 41 } 42 43 pub struct OpenFirmwareFdtDriver; 44 45 impl OpenFirmwareFdtDriver { 46 #[allow(dead_code)] 47 pub fn early_scan_device_tree(&self) -> Result<(), SystemError> { 48 let fdt_vaddr = boot_params().read().fdt().unwrap(); 49 let fdt = unsafe { 50 fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| { 51 kerror!("failed to parse fdt, err={:?}", e); 52 SystemError::EINVAL 53 }) 54 }?; 55 56 self.early_init_scan_nodes(&fdt); 57 58 return Ok(()); 59 } 60 61 fn early_init_scan_nodes(&self, fdt: &Fdt) { 62 self.early_init_scan_root(fdt) 63 .expect("Failed to scan fdt root node."); 64 65 self.early_init_scan_chosen(fdt).unwrap_or_else(|_| { 66 kwarn!("No `chosen` node found"); 67 }); 68 69 self.early_init_scan_memory(fdt); 70 } 71 72 /// 扫描根节点 73 fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> { 74 let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?; 75 76 let mut guard = FDT_GLOBAL_DATA.write(); 77 78 if let Some(prop) = node.property("#size-cells") { 79 guard.root_size_cells = prop.as_usize().unwrap() as u32; 80 81 // kdebug!("fdt_root_size_cells={}", guard.root_size_cells); 82 } 83 84 if let Some(prop) = node.property("#address-cells") { 85 guard.root_addr_cells = prop.as_usize().unwrap() as u32; 86 87 // kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells); 88 } 89 90 return Ok(()); 91 } 92 93 /// 扫描 `/chosen` 节点 94 fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> { 95 const CHOSEN_NAME1: &str = "/chosen"; 96 let mut node = fdt.find_node(CHOSEN_NAME1); 97 if node.is_none() { 98 const CHOSEN_NAME2: &str = "/chosen@0"; 99 node = fdt.find_node(CHOSEN_NAME2); 100 if node.is_some() { 101 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2); 102 } 103 } else { 104 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1); 105 } 106 107 if let Some(node) = node { 108 if let Some(prop) = node.property("bootargs") { 109 let bootargs = prop.as_str().unwrap(); 110 111 boot_params() 112 .write() 113 .boot_cmdline_append(bootargs.as_bytes()); 114 } 115 } 116 117 // TODO: 拼接内核自定义的command line参数 118 119 kdebug!("Command line: {}", boot_params().read().boot_cmdline_str()); 120 return Ok(()); 121 } 122 123 /// 扫描 `/memory` 节点 124 /// 125 /// ## 参数 126 /// 127 /// - `fdt`:FDT 128 /// 129 /// ## 返回值 130 /// 131 /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。 132 fn early_init_scan_memory(&self, fdt: &Fdt) -> bool { 133 let mut found_memory = false; 134 for node in fdt.all_nodes() { 135 let device_type: Option<NodeProperty<'_>> = node.property("device_type"); 136 if device_type.is_none() { 137 continue; 138 } 139 let device_type = device_type.unwrap().as_str(); 140 if device_type.is_none() || device_type.unwrap() != "memory" { 141 continue; 142 } 143 144 if !self.is_device_avaliable(&node) { 145 continue; 146 } 147 148 let reg = node.property("reg"); 149 if reg.is_none() { 150 continue; 151 } 152 let reg = reg.unwrap(); 153 // 每个cell是4字节 154 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize; 155 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize; 156 157 let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4); 158 159 for i in 0..total_elements_in_reg { 160 let base_index = i * (addr_cells + size_cells); 161 162 let (base, base_index) = read_cell(reg.value, base_index, addr_cells); 163 let (size, _) = read_cell(reg.value, base_index, size_cells); 164 165 if size == 0 { 166 continue; 167 } 168 169 kdebug!("Found memory: base={:#x}, size={:#x}", base, size); 170 self.early_init_dt_add_memory(base, size); 171 found_memory = true; 172 } 173 } 174 175 return found_memory; 176 } 177 178 #[cfg(target_arch = "x86_64")] 179 pub fn early_init_dt_add_memory(&self, _base: u64, _size: u64) { 180 kBUG!("x86_64 should not call early_init_dt_add_memory"); 181 } 182 183 #[cfg(not(target_arch = "x86_64"))] 184 pub fn early_init_dt_add_memory(&self, base: u64, size: u64) { 185 use crate::{ 186 arch::MMArch, 187 libs::align::page_align_down, 188 mm::{ 189 memblock::{mem_block_manager, MemBlockManager}, 190 MemoryManagementArch, PhysAddr, 191 }, 192 }; 193 194 let mut base = base as usize; 195 let mut size = size as usize; 196 197 if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) { 198 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 199 } 200 201 if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false { 202 size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK)); 203 base = page_align_down(base); 204 } 205 206 size = page_align_down(size); 207 208 if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 209 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 210 } 211 212 if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 213 kwarn!( 214 "Ignoring memory range {:#x}-{:#x}", 215 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1, 216 base + size 217 ); 218 size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1; 219 } 220 221 if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 222 kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size); 223 return; 224 } 225 226 if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 227 { 228 kwarn!( 229 "Ignoring memory range {:#x}-{:#x}", 230 base, 231 MemBlockManager::MIN_MEMBLOCK_ADDR.data() 232 ); 233 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base; 234 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data(); 235 } 236 } 237 238 mem_block_manager() 239 .add_block(PhysAddr::new(base), size) 240 .unwrap_or_else(|e| { 241 panic!( 242 "Failed to add memory block '{:#x}-{:#x}', err={:?}", 243 base, 244 base + size, 245 e 246 ); 247 }); 248 } 249 250 /// 判断设备是否可用 251 fn is_device_avaliable(&self, node: &FdtNode) -> bool { 252 let status = node.property("status"); 253 if status.is_none() { 254 return true; 255 } 256 257 let status = status.unwrap().as_str(); 258 if let Some(status) = status { 259 if status == "okay" || status == "ok" { 260 return true; 261 } 262 } 263 264 return false; 265 } 266 267 /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存 268 /// 269 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634 270 pub fn early_init_fdt_scan_reserved_mem(&self) { 271 let vaddr = boot_params().read().fdt(); 272 if vaddr.is_none() { 273 return; 274 } 275 let vaddr = vaddr.unwrap(); 276 let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) }; 277 if fdt.is_err() { 278 return; 279 } 280 281 let fdt = fdt.unwrap(); 282 self.early_reserve_fdt_itself(&fdt); 283 284 let reserved_mem_nodes = fdt.memory_reservations(); 285 286 for node in reserved_mem_nodes { 287 if node.size() != 0 { 288 let address = PhysAddr::new(node.address() as usize); 289 let size = node.size(); 290 kdebug!("Reserve memory: {:?}-{:?}", address, address + size); 291 mem_block_manager().reserve_block(address, size).unwrap(); 292 } 293 } 294 295 self.fdt_scan_reserved_mem(&fdt) 296 .expect("Failed to scan reserved memory"); 297 } 298 299 /// 保留fdt自身的内存空间 300 301 fn early_reserve_fdt_itself(&self, fdt: &Fdt) { 302 #[cfg(target_arch = "riscv64")] 303 { 304 use crate::libs::align::{page_align_down, page_align_up}; 305 306 let fdt_paddr = boot_params().read().arch.fdt_paddr; 307 let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data())); 308 let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size()); 309 mem_block_manager() 310 .reserve_block(rsvd_start, rsvd_size) 311 .expect("Failed to reserve memory for fdt"); 312 } 313 314 #[cfg(target_arch = "x86_64")] 315 { 316 let _ = fdt; 317 } 318 } 319 320 fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> { 321 let node = fdt 322 .find_node("/reserved-memory") 323 .ok_or(SystemError::ENODEV)?; 324 325 for child in node.children() { 326 if !self.is_device_avaliable(&child) { 327 continue; 328 } 329 330 reserved_mem_reserve_reg(&child).ok(); 331 } 332 333 return Ok(()); 334 } 335 336 fn early_init_dt_reserve_memory( 337 &self, 338 base: PhysAddr, 339 size: usize, 340 nomap: bool, 341 ) -> Result<(), SystemError> { 342 if nomap { 343 if mem_block_manager().is_overlapped(base, size) 344 && mem_block_manager().is_overlapped_with_reserved(base, size) 345 { 346 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`, 347 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。 348 return Err(SystemError::EBUSY); 349 } 350 351 return mem_block_manager().mark_nomap(base, size); 352 } 353 354 return mem_block_manager().reserve_block(base, size); 355 } 356 } 357 358 #[allow(dead_code)] 359 fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> { 360 let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> = 361 FDT_GLOBAL_DATA.read(); 362 let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize) 363 * size_of::<u32>(); 364 drop(global_data_guard); 365 366 let reg = node.property("reg").ok_or(SystemError::ENOENT)?; 367 368 let mut reg_size = reg.value.len(); 369 if reg_size > 0 && reg_size % t_len != 0 { 370 kerror!( 371 "Reserved memory: invalid reg property in '{}', skipping node.", 372 node.name 373 ); 374 return Err(SystemError::EINVAL); 375 } 376 // 每个cell是4字节 377 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize; 378 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize; 379 380 let nomap = node.property("no-map").is_some(); 381 382 let mut base_index = 0; 383 384 while reg_size >= t_len { 385 let (base, bi) = read_cell(reg.value, base_index, addr_cells); 386 base_index = bi; 387 let (size, bi) = read_cell(reg.value, base_index, size_cells); 388 base_index = bi; 389 390 if size > 0 391 && open_firmware_fdt_driver() 392 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap) 393 .is_ok() 394 { 395 kdebug!( 396 "Reserved memory: base={:#x}, size={:#x}, nomap={}", 397 base, 398 size, 399 nomap 400 ); 401 } else { 402 kerror!( 403 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}", 404 base, 405 size, 406 nomap 407 ); 408 } 409 410 reg_size -= t_len; 411 412 // todo: linux这里保存了节点,但是我感觉现在还用不着。 413 } 414 415 return Ok(()); 416 } 417 418 /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回 419 /// 420 /// ## 参数 421 /// 422 /// - `reg_value`:`reg`属性数组的引用 423 /// - `base_index`:起始索引 424 /// - `cells`:要读取的cell数量,必须是1或2 425 /// 426 /// ## 返回值 427 /// 428 /// (value, next_base_index) 429 fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) { 430 let next_base_index = base_index + cells * 4; 431 match cells { 432 1 => { 433 return ( 434 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap()) 435 .try_into() 436 .unwrap(), 437 next_base_index, 438 ); 439 } 440 441 2 => { 442 return ( 443 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()), 444 next_base_index, 445 ); 446 } 447 _ => { 448 panic!("cells must be 1 or 2"); 449 } 450 } 451 } 452