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