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