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