xref: /DragonOS/kernel/src/driver/open_firmware/fdt.rs (revision 2709e017d0d216d61b2caed3c7286459de7794c7)
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().unwrap();
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::{
217                 memblock::{mem_block_manager, MemBlockManager},
218                 MemoryManagementArch, PhysAddr,
219             },
220         };
221 
222         let mut base = base as usize;
223         let mut size = size as usize;
224 
225         if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) {
226             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
227         }
228 
229         if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false {
230             size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK));
231             base = page_align_down(base);
232         }
233 
234         size = page_align_down(size);
235 
236         if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
237             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
238         }
239 
240         if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
241             kwarn!(
242                 "Ignoring memory range {:#x}-{:#x}",
243                 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1,
244                 base + size
245             );
246             size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1;
247         }
248 
249         if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
250             kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size);
251             return;
252         }
253 
254         if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
255             {
256                 kwarn!(
257                     "Ignoring memory range {:#x}-{:#x}",
258                     base,
259                     MemBlockManager::MIN_MEMBLOCK_ADDR.data()
260                 );
261                 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
262                 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
263             }
264         }
265 
266         mem_block_manager()
267             .add_block(PhysAddr::new(base), size)
268             .unwrap_or_else(|e| {
269                 panic!(
270                     "Failed to add memory block '{:#x}-{:#x}', err={:?}",
271                     base,
272                     base + size,
273                     e
274                 );
275             });
276     }
277 
278     /// 判断设备是否可用
279     fn is_device_avaliable(&self, node: &FdtNode) -> bool {
280         let status = node.property("status");
281         if status.is_none() {
282             return true;
283         }
284 
285         let status = status.unwrap().as_str();
286         if let Some(status) = status {
287             if status == "okay" || status == "ok" {
288                 return true;
289             }
290         }
291 
292         return false;
293     }
294 
295     /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
296     ///
297     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
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                 kdebug!("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自身的内存空间
328 
329     fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
330         #[cfg(target_arch = "riscv64")]
331         {
332             use crate::libs::align::{page_align_down, page_align_up};
333 
334             let fdt_paddr = boot_params().read().arch.fdt_paddr;
335             let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
336             let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
337             mem_block_manager()
338                 .reserve_block(rsvd_start, rsvd_size)
339                 .expect("Failed to reserve memory for fdt");
340         }
341 
342         #[cfg(target_arch = "x86_64")]
343         {
344             let _ = fdt;
345         }
346     }
347 
348     fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
349         let node = fdt
350             .find_node("/reserved-memory")
351             .ok_or(SystemError::ENODEV)?;
352 
353         for child in node.children() {
354             if !self.is_device_avaliable(&child) {
355                 continue;
356             }
357 
358             reserved_mem_reserve_reg(&child).ok();
359         }
360 
361         return Ok(());
362     }
363 
364     fn early_init_dt_reserve_memory(
365         &self,
366         base: PhysAddr,
367         size: usize,
368         nomap: bool,
369     ) -> Result<(), SystemError> {
370         if nomap {
371             if mem_block_manager().is_overlapped(base, size)
372                 && mem_block_manager().is_overlapped_with_reserved(base, size)
373             {
374                 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
375                 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
376                 return Err(SystemError::EBUSY);
377             }
378 
379             return mem_block_manager().mark_nomap(base, size);
380         }
381 
382         return mem_block_manager().reserve_block(base, size);
383     }
384 }
385 
386 #[allow(dead_code)]
387 fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
388     let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
389         FDT_GLOBAL_DATA.read();
390     let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
391         * size_of::<u32>();
392     drop(global_data_guard);
393 
394     let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
395 
396     let mut reg_size = reg.value.len();
397     if reg_size > 0 && reg_size % t_len != 0 {
398         kerror!(
399             "Reserved memory: invalid reg property in '{}', skipping node.",
400             node.name
401         );
402         return Err(SystemError::EINVAL);
403     }
404     // 每个cell是4字节
405     let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
406     let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
407 
408     let nomap = node.property("no-map").is_some();
409 
410     let mut base_index = 0;
411 
412     while reg_size >= t_len {
413         let (base, bi) = read_cell(reg.value, base_index, addr_cells);
414         base_index = bi;
415         let (size, bi) = read_cell(reg.value, base_index, size_cells);
416         base_index = bi;
417 
418         if size > 0
419             && open_firmware_fdt_driver()
420                 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
421                 .is_ok()
422         {
423             kdebug!(
424                 "Reserved memory: base={:#x}, size={:#x}, nomap={}",
425                 base,
426                 size,
427                 nomap
428             );
429         } else {
430             kerror!(
431                 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
432                 base,
433                 size,
434                 nomap
435             );
436         }
437 
438         reg_size -= t_len;
439 
440         // todo: linux这里保存了节点,但是我感觉现在还用不着。
441     }
442 
443     return Ok(());
444 }
445 
446 /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
447 ///
448 /// ## 参数
449 ///
450 /// - `reg_value`:`reg`属性数组的引用
451 /// - `base_index`:起始索引
452 /// - `cells`:要读取的cell数量,必须是1或2
453 ///
454 /// ## 返回值
455 ///
456 /// (value, next_base_index)
457 fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
458     let next_base_index = base_index + cells * 4;
459     match cells {
460         1 => {
461             return (
462                 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
463                     .try_into()
464                     .unwrap(),
465                 next_base_index,
466             );
467         }
468 
469         2 => {
470             return (
471                 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
472                 next_base_index,
473             );
474         }
475         _ => {
476             panic!("cells must be 1 or 2");
477         }
478     }
479 }
480