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().unwrap(); 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::{ 217 memblock::{mem_block_manager, MemBlockManager}, 218 MemoryManagementArch, PhysAddr, 219 }, 220 }; 221 222 let mut base = base as usize; 223 let mut size = size as usize; 224 225 if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) { 226 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 227 } 228 229 if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false { 230 size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK)); 231 base = page_align_down(base); 232 } 233 234 size = page_align_down(size); 235 236 if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 237 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 238 } 239 240 if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 241 kwarn!( 242 "Ignoring memory range {:#x}-{:#x}", 243 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1, 244 base + size 245 ); 246 size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1; 247 } 248 249 if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 250 kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size); 251 return; 252 } 253 254 if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 255 { 256 kwarn!( 257 "Ignoring memory range {:#x}-{:#x}", 258 base, 259 MemBlockManager::MIN_MEMBLOCK_ADDR.data() 260 ); 261 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base; 262 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data(); 263 } 264 } 265 266 mem_block_manager() 267 .add_block(PhysAddr::new(base), size) 268 .unwrap_or_else(|e| { 269 panic!( 270 "Failed to add memory block '{:#x}-{:#x}', err={:?}", 271 base, 272 base + size, 273 e 274 ); 275 }); 276 } 277 278 /// 判断设备是否可用 279 fn is_device_avaliable(&self, node: &FdtNode) -> bool { 280 let status = node.property("status"); 281 if status.is_none() { 282 return true; 283 } 284 285 let status = status.unwrap().as_str(); 286 if let Some(status) = status { 287 if status == "okay" || status == "ok" { 288 return true; 289 } 290 } 291 292 return false; 293 } 294 295 /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存 296 /// 297 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634 298 pub fn early_init_fdt_scan_reserved_mem(&self) { 299 let vaddr = boot_params().read().fdt(); 300 if vaddr.is_none() { 301 return; 302 } 303 let vaddr = vaddr.unwrap(); 304 let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) }; 305 if fdt.is_err() { 306 return; 307 } 308 309 let fdt = fdt.unwrap(); 310 self.early_reserve_fdt_itself(&fdt); 311 312 let reserved_mem_nodes = fdt.memory_reservations(); 313 314 for node in reserved_mem_nodes { 315 if node.size() != 0 { 316 let address = PhysAddr::new(node.address() as usize); 317 let size = node.size(); 318 kdebug!("Reserve memory: {:?}-{:?}", address, address + size); 319 mem_block_manager().reserve_block(address, size).unwrap(); 320 } 321 } 322 323 self.fdt_scan_reserved_mem(&fdt) 324 .expect("Failed to scan reserved memory"); 325 } 326 327 /// 保留fdt自身的内存空间 328 329 fn early_reserve_fdt_itself(&self, fdt: &Fdt) { 330 #[cfg(target_arch = "riscv64")] 331 { 332 use crate::libs::align::{page_align_down, page_align_up}; 333 334 let fdt_paddr = boot_params().read().arch.fdt_paddr; 335 let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data())); 336 let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size()); 337 mem_block_manager() 338 .reserve_block(rsvd_start, rsvd_size) 339 .expect("Failed to reserve memory for fdt"); 340 } 341 342 #[cfg(target_arch = "x86_64")] 343 { 344 let _ = fdt; 345 } 346 } 347 348 fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> { 349 let node = fdt 350 .find_node("/reserved-memory") 351 .ok_or(SystemError::ENODEV)?; 352 353 for child in node.children() { 354 if !self.is_device_avaliable(&child) { 355 continue; 356 } 357 358 reserved_mem_reserve_reg(&child).ok(); 359 } 360 361 return Ok(()); 362 } 363 364 fn early_init_dt_reserve_memory( 365 &self, 366 base: PhysAddr, 367 size: usize, 368 nomap: bool, 369 ) -> Result<(), SystemError> { 370 if nomap { 371 if mem_block_manager().is_overlapped(base, size) 372 && mem_block_manager().is_overlapped_with_reserved(base, size) 373 { 374 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`, 375 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。 376 return Err(SystemError::EBUSY); 377 } 378 379 return mem_block_manager().mark_nomap(base, size); 380 } 381 382 return mem_block_manager().reserve_block(base, size); 383 } 384 385 pub fn find_node_by_compatible<'b>( 386 &self, 387 fdt: &'b Fdt<'b>, 388 compatible: &'b str, 389 ) -> impl Iterator<Item = fdt::node::FdtNode<'b, 'b>> + 'b { 390 // compatible = compatible.trim(); 391 let r = fdt.all_nodes().filter(move |x| { 392 x.compatible() 393 .is_some_and(|x| x.all().any(|x| x == compatible)) 394 }); 395 396 return r; 397 } 398 } 399 400 #[allow(dead_code)] 401 fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> { 402 let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> = 403 FDT_GLOBAL_DATA.read(); 404 let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize) 405 * size_of::<u32>(); 406 drop(global_data_guard); 407 408 let reg = node.property("reg").ok_or(SystemError::ENOENT)?; 409 410 let mut reg_size = reg.value.len(); 411 if reg_size > 0 && reg_size % t_len != 0 { 412 kerror!( 413 "Reserved memory: invalid reg property in '{}', skipping node.", 414 node.name 415 ); 416 return Err(SystemError::EINVAL); 417 } 418 // 每个cell是4字节 419 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize; 420 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize; 421 422 let nomap = node.property("no-map").is_some(); 423 424 let mut base_index = 0; 425 426 while reg_size >= t_len { 427 let (base, bi) = read_cell(reg.value, base_index, addr_cells); 428 base_index = bi; 429 let (size, bi) = read_cell(reg.value, base_index, size_cells); 430 base_index = bi; 431 432 if size > 0 433 && open_firmware_fdt_driver() 434 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap) 435 .is_ok() 436 { 437 kdebug!( 438 "Reserved memory: base={:#x}, size={:#x}, nomap={}", 439 base, 440 size, 441 nomap 442 ); 443 } else { 444 kerror!( 445 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}", 446 base, 447 size, 448 nomap 449 ); 450 } 451 452 reg_size -= t_len; 453 454 // todo: linux这里保存了节点,但是我感觉现在还用不着。 455 } 456 457 return Ok(()); 458 } 459 460 /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回 461 /// 462 /// ## 参数 463 /// 464 /// - `reg_value`:`reg`属性数组的引用 465 /// - `base_index`:起始索引 466 /// - `cells`:要读取的cell数量,必须是1或2 467 /// 468 /// ## 返回值 469 /// 470 /// (value, next_base_index) 471 fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) { 472 let next_base_index = base_index + cells * 4; 473 match cells { 474 1 => { 475 return ( 476 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap()) 477 .try_into() 478 .unwrap(), 479 next_base_index, 480 ); 481 } 482 483 2 => { 484 return ( 485 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()), 486 next_base_index, 487 ); 488 } 489 _ => { 490 panic!("cells must be 1 or 2"); 491 } 492 } 493 } 494