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