1 use fdt::{ 2 node::{FdtNode, NodeProperty}, 3 Fdt, 4 }; 5 use system_error::SystemError; 6 7 use crate::{init::boot_params, libs::rwlock::RwLock}; 8 9 #[inline(always)] 10 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver { 11 &OpenFirmwareFdtDriver 12 } 13 14 static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new()); 15 16 #[derive(Debug)] 17 struct FdtGlobalData { 18 /// FDT根节点下的`size-cells`属性值 19 root_size_cells: u32, 20 21 /// FDT根节点下的`address-cells`属性值 22 root_addr_cells: u32, 23 24 chosen_node_name: Option<&'static str>, 25 } 26 27 impl FdtGlobalData { 28 pub const fn new() -> Self { 29 Self { 30 root_size_cells: 1, 31 root_addr_cells: 1, 32 chosen_node_name: None, 33 } 34 } 35 } 36 37 pub struct OpenFirmwareFdtDriver; 38 39 impl OpenFirmwareFdtDriver { 40 #[allow(dead_code)] 41 pub fn early_scan_device_tree(&self) -> Result<(), SystemError> { 42 let fdt_vaddr = boot_params().read().fdt().unwrap(); 43 let fdt = unsafe { 44 fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| { 45 kerror!("failed to parse fdt, err={:?}", e); 46 SystemError::EINVAL 47 }) 48 }?; 49 50 self.early_init_scan_nodes(&fdt); 51 52 return Ok(()); 53 } 54 55 fn early_init_scan_nodes(&self, fdt: &Fdt) { 56 self.early_init_scan_root(fdt) 57 .expect("Failed to scan fdt root node."); 58 59 self.early_init_scan_chosen(fdt).unwrap_or_else(|_| { 60 kwarn!("No `chosen` node found"); 61 }); 62 63 self.early_init_scan_memory(fdt); 64 } 65 66 /// 扫描根节点 67 fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> { 68 let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?; 69 70 let mut guard = FDT_GLOBAL_DATA.write(); 71 72 if let Some(prop) = node.property("#size-cells") { 73 guard.root_size_cells = prop.as_usize().unwrap() as u32; 74 75 kdebug!("fdt_root_size_cells={}", guard.root_size_cells); 76 } 77 78 if let Some(prop) = node.property("#address-cells") { 79 guard.root_addr_cells = prop.as_usize().unwrap() as u32; 80 81 kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells); 82 } 83 84 return Ok(()); 85 } 86 87 /// 扫描 `/chosen` 节点 88 fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> { 89 const CHOSEN_NAME1: &'static str = "/chosen"; 90 let mut node = fdt.find_node(CHOSEN_NAME1); 91 if node.is_none() { 92 const CHOSEN_NAME2: &'static str = "/chosen@0"; 93 node = fdt.find_node(CHOSEN_NAME2); 94 if node.is_some() { 95 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2); 96 } 97 } else { 98 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1); 99 } 100 101 if let Some(node) = node { 102 if let Some(prop) = node.property("bootargs") { 103 let bootargs = prop.as_str().unwrap(); 104 105 boot_params() 106 .write() 107 .boot_cmdline_append(bootargs.as_bytes()); 108 } 109 } 110 111 // TODO: 拼接内核自定义的command line参数 112 113 kdebug!("Command line: {}", boot_params().read().boot_cmdline_str()); 114 return Ok(()); 115 } 116 117 /// 扫描 `/memory` 节点 118 /// 119 /// ## 参数 120 /// 121 /// - `fdt`:FDT 122 /// 123 /// ## 返回值 124 /// 125 /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。 126 fn early_init_scan_memory(&self, fdt: &Fdt) -> bool { 127 let mut found_memory = false; 128 for node in fdt.all_nodes() { 129 let device_type: Option<NodeProperty<'_>> = node.property("device_type"); 130 if device_type.is_none() { 131 continue; 132 } 133 let device_type = device_type.unwrap().as_str(); 134 if device_type.is_none() || device_type.unwrap() != "memory" { 135 continue; 136 } 137 138 if !self.is_device_avaliable(&node) { 139 continue; 140 } 141 142 let reg = node.property("reg"); 143 if reg.is_none() { 144 continue; 145 } 146 let reg = reg.unwrap(); 147 // 每个cell是4字节 148 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize; 149 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize; 150 151 let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4); 152 153 for i in 0..total_elements_in_reg { 154 let mut base_index = i * (addr_cells + size_cells); 155 let base: u64; 156 let size: u64; 157 match addr_cells { 158 1 => { 159 base = u32::from_be_bytes( 160 reg.value[base_index..base_index + 4].try_into().unwrap(), 161 ) as u64; 162 } 163 2 => { 164 base = u64::from_be_bytes( 165 reg.value[base_index..base_index + 8].try_into().unwrap(), 166 ); 167 } 168 _ => { 169 panic!("addr_cells must be 1 or 2"); 170 } 171 } 172 base_index += addr_cells * 4; 173 174 match size_cells { 175 1 => { 176 size = u32::from_be_bytes( 177 reg.value[base_index..base_index + 4].try_into().unwrap(), 178 ) as u64; 179 } 180 2 => { 181 size = u64::from_be_bytes( 182 reg.value[base_index..base_index + 8].try_into().unwrap(), 183 ); 184 } 185 _ => { 186 panic!("size_cells must be 1 or 2"); 187 } 188 } 189 190 if size == 0 { 191 continue; 192 } 193 194 kdebug!("Found memory: base={:#x}, size={:#x}", base, size); 195 self.early_init_dt_add_memory(base, size); 196 found_memory = true; 197 } 198 } 199 200 return found_memory; 201 } 202 203 #[cfg(target_arch = "x86_64")] 204 pub fn early_init_dt_add_memory(&self, _base: u64, _size: u64) { 205 kBUG!("x86_64 should not call early_init_dt_add_memory"); 206 } 207 208 #[cfg(not(target_arch = "x86_64"))] 209 pub fn early_init_dt_add_memory(&self, base: u64, size: u64) { 210 use crate::{ 211 arch::MMArch, 212 libs::align::page_align_down, 213 mm::{ 214 memblock::{mem_block_manager, MemBlockManager}, 215 MemoryManagementArch, PhysAddr, 216 }, 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 mem_block_manager() 263 .add_block(PhysAddr::new(base), size) 264 .unwrap_or_else(|e| { 265 panic!( 266 "Failed to add memory block '{:#x}-{:#x}', err={:?}", 267 base, 268 base + size, 269 e 270 ); 271 }); 272 } 273 } 274 275 fn is_device_avaliable(&self, node: &FdtNode) -> bool { 276 let status = node.property("status"); 277 if status.is_none() { 278 return true; 279 } 280 281 let status = status.unwrap().as_str(); 282 if let Some(status) = status { 283 if status == "okay" || status == "ok" { 284 return true; 285 } 286 } 287 288 return false; 289 } 290 } 291