1 use fdt::{ 2 node::{FdtNode, NodeProperty}, 3 Fdt, 4 }; 5 use system_error::SystemError; 6 7 use crate::{ 8 arch::MMArch, 9 init::boot_params, 10 libs::{align::page_align_down, rwlock::RwLock}, 11 mm::{ 12 memblock::{mem_block_manager, MemBlockManager}, 13 MemoryManagementArch, PhysAddr, VirtAddr, 14 }, 15 }; 16 17 #[inline(always)] 18 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver { 19 &OpenFirmwareFdtDriver 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 static mut FDT_VADDR: Option<VirtAddr> = None; 46 47 pub struct OpenFirmwareFdtDriver; 48 49 impl OpenFirmwareFdtDriver { 50 pub fn early_scan_device_tree(&self) -> Result<(), SystemError> { 51 let fdt_vaddr = unsafe { FDT_VADDR.ok_or(SystemError::EINVAL)? }; 52 let fdt = unsafe { 53 fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| { 54 kerror!("failed to parse fdt, err={:?}", e); 55 SystemError::EINVAL 56 }) 57 }?; 58 59 self.early_init_scan_nodes(&fdt); 60 61 return Ok(()); 62 } 63 64 fn early_init_scan_nodes(&self, fdt: &Fdt) { 65 self.early_init_scan_root(fdt) 66 .expect("Failed to scan fdt root node."); 67 68 self.early_init_scan_chosen(fdt).unwrap_or_else(|_| { 69 kwarn!("No `chosen` node found"); 70 }); 71 72 self.early_init_scan_memory(fdt); 73 } 74 75 /// 扫描根节点 76 fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> { 77 let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?; 78 79 let mut guard = FDT_GLOBAL_DATA.write(); 80 81 if let Some(prop) = node.property("#size-cells") { 82 guard.root_size_cells = prop.as_usize().unwrap() as u32; 83 84 kdebug!("fdt_root_size_cells={}", guard.root_size_cells); 85 } 86 87 if let Some(prop) = node.property("#address-cells") { 88 guard.root_addr_cells = prop.as_usize().unwrap() as u32; 89 90 kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells); 91 } 92 93 return Ok(()); 94 } 95 96 /// 扫描 `/chosen` 节点 97 fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> { 98 const CHOSEN_NAME1: &'static str = "/chosen"; 99 let mut node = fdt.find_node(CHOSEN_NAME1); 100 if node.is_none() { 101 const CHOSEN_NAME2: &'static str = "/chosen@0"; 102 node = fdt.find_node(CHOSEN_NAME2); 103 if node.is_some() { 104 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2); 105 } 106 } else { 107 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1); 108 } 109 110 if let Some(node) = node { 111 if let Some(prop) = node.property("bootargs") { 112 let bootargs = prop.as_str().unwrap(); 113 114 boot_params() 115 .write() 116 .boot_cmdline_append(bootargs.as_bytes()); 117 } 118 } 119 120 // TODO: 拼接内核自定义的command line参数 121 122 kdebug!("Command line: {}", boot_params().read().boot_cmdline_str()); 123 return Ok(()); 124 } 125 126 /// 扫描 `/memory` 节点 127 /// 128 /// ## 参数 129 /// 130 /// - `fdt`:FDT 131 /// 132 /// ## 返回值 133 /// 134 /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。 135 fn early_init_scan_memory(&self, fdt: &Fdt) -> bool { 136 let mut found_memory = false; 137 for node in fdt.all_nodes() { 138 let device_type: Option<NodeProperty<'_>> = node.property("device_type"); 139 if device_type.is_none() { 140 continue; 141 } 142 let device_type = device_type.unwrap().as_str(); 143 if device_type.is_none() || device_type.unwrap() != "memory" { 144 continue; 145 } 146 147 if !self.is_device_avaliable(&node) { 148 continue; 149 } 150 151 let reg = node.property("reg"); 152 if reg.is_none() { 153 continue; 154 } 155 let reg = reg.unwrap(); 156 // 每个cell是4字节 157 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize; 158 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize; 159 160 let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4); 161 162 for i in 0..total_elements_in_reg { 163 let mut base_index = i * (addr_cells + size_cells); 164 let base: u64; 165 let size: u64; 166 match addr_cells { 167 1 => { 168 base = u32::from_be_bytes( 169 reg.value[base_index..base_index + 4].try_into().unwrap(), 170 ) as u64; 171 } 172 2 => { 173 base = u64::from_be_bytes( 174 reg.value[base_index..base_index + 8].try_into().unwrap(), 175 ); 176 } 177 _ => { 178 panic!("addr_cells must be 1 or 2"); 179 } 180 } 181 base_index += addr_cells * 4; 182 183 match size_cells { 184 1 => { 185 size = u32::from_be_bytes( 186 reg.value[base_index..base_index + 4].try_into().unwrap(), 187 ) as u64; 188 } 189 2 => { 190 size = u64::from_be_bytes( 191 reg.value[base_index..base_index + 8].try_into().unwrap(), 192 ); 193 } 194 _ => { 195 panic!("size_cells must be 1 or 2"); 196 } 197 } 198 199 if size == 0 { 200 continue; 201 } 202 203 kdebug!("Found memory: base={:#x}, size={:#x}", base, size); 204 self.early_init_dt_add_memory(base, size); 205 found_memory = true; 206 } 207 } 208 209 return found_memory; 210 } 211 212 fn early_init_dt_add_memory(&self, base: u64, size: u64) { 213 let mut base = base as usize; 214 let mut size = size as usize; 215 216 if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) { 217 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 218 } 219 220 if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false { 221 size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK)); 222 base = page_align_down(base); 223 } 224 225 size = page_align_down(size); 226 227 if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 228 kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size); 229 } 230 231 if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() { 232 kwarn!( 233 "Ignoring memory range {:#x}-{:#x}", 234 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1, 235 base + size 236 ); 237 size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1; 238 } 239 240 if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 241 kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size); 242 return; 243 } 244 245 if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() { 246 { 247 kwarn!( 248 "Ignoring memory range {:#x}-{:#x}", 249 base, 250 MemBlockManager::MIN_MEMBLOCK_ADDR.data() 251 ); 252 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base; 253 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data(); 254 } 255 256 mem_block_manager() 257 .add_block(PhysAddr::new(base), size) 258 .unwrap_or_else(|e| { 259 panic!( 260 "Failed to add memory block '{:#x}-{:#x}', err={:?}", 261 base, 262 base + size, 263 e 264 ); 265 }); 266 } 267 } 268 269 fn is_device_avaliable(&self, node: &FdtNode) -> bool { 270 let status = node.property("status"); 271 if status.is_none() { 272 return true; 273 } 274 275 let status = status.unwrap().as_str(); 276 if let Some(status) = status { 277 if status == "okay" || status == "ok" { 278 return true; 279 } 280 } 281 282 return false; 283 } 284 285 pub unsafe fn set_fdt_vaddr(&self, vaddr: VirtAddr) -> Result<(), SystemError> { 286 if vaddr.is_null() { 287 return Err(SystemError::EINVAL); 288 } 289 fdt::Fdt::from_ptr(vaddr.as_ptr()).map_err(|e| { 290 kerror!("failed to parse fdt, err={:?}", e); 291 SystemError::EINVAL 292 })?; 293 294 unsafe { 295 FDT_VADDR = Some(vaddr); 296 } 297 298 Ok(()) 299 } 300 } 301