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