xref: /DragonOS/kernel/src/driver/open_firmware/fdt.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
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)]
16 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 {
34     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)]
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 
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     /// 扫描根节点
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` 节点
94     fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> {
95         const CHOSEN_NAME1: &str = "/chosen";
96         let mut node = fdt.find_node(CHOSEN_NAME1);
97         if node.is_none() {
98             const CHOSEN_NAME2: &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`。
132     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")]
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"))]
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     /// 判断设备是否可用
251     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
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 
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 
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 
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)]
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)
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