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