xref: /DragonOS/kernel/src/driver/open_firmware/fdt.rs (revision 3e3c6316aaac5a8a2932bd1746ec8b900dc5e2c6)
1 use fdt::{
2     node::{FdtNode, NodeProperty},
3     Fdt,
4 };
5 use system_error::SystemError;
6 
7 use crate::{
8     arch::MMArch,
9     init::boot_params,
10     libs::{align::page_align_down, rwlock::RwLock},
11     mm::{
12         memblock::{mem_block_manager, MemBlockManager},
13         MemoryManagementArch, PhysAddr, VirtAddr,
14     },
15 };
16 
17 #[inline(always)]
18 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
19     &OpenFirmwareFdtDriver
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 static mut FDT_VADDR: Option<VirtAddr> = None;
46 
47 pub struct OpenFirmwareFdtDriver;
48 
49 impl OpenFirmwareFdtDriver {
50     pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
51         let fdt_vaddr = unsafe { FDT_VADDR.ok_or(SystemError::EINVAL)? };
52         let fdt = unsafe {
53             fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
54                 kerror!("failed to parse fdt, err={:?}", e);
55                 SystemError::EINVAL
56             })
57         }?;
58 
59         self.early_init_scan_nodes(&fdt);
60 
61         return Ok(());
62     }
63 
64     fn early_init_scan_nodes(&self, fdt: &Fdt) {
65         self.early_init_scan_root(fdt)
66             .expect("Failed to scan fdt root node.");
67 
68         self.early_init_scan_chosen(fdt).unwrap_or_else(|_| {
69             kwarn!("No `chosen` node found");
70         });
71 
72         self.early_init_scan_memory(fdt);
73     }
74 
75     /// 扫描根节点
76     fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> {
77         let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?;
78 
79         let mut guard = FDT_GLOBAL_DATA.write();
80 
81         if let Some(prop) = node.property("#size-cells") {
82             guard.root_size_cells = prop.as_usize().unwrap() as u32;
83 
84             kdebug!("fdt_root_size_cells={}", guard.root_size_cells);
85         }
86 
87         if let Some(prop) = node.property("#address-cells") {
88             guard.root_addr_cells = prop.as_usize().unwrap() as u32;
89 
90             kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
91         }
92 
93         return Ok(());
94     }
95 
96     /// 扫描 `/chosen` 节点
97     fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> {
98         const CHOSEN_NAME1: &'static str = "/chosen";
99         let mut node = fdt.find_node(CHOSEN_NAME1);
100         if node.is_none() {
101             const CHOSEN_NAME2: &'static str = "/chosen@0";
102             node = fdt.find_node(CHOSEN_NAME2);
103             if node.is_some() {
104                 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2);
105             }
106         } else {
107             FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1);
108         }
109 
110         if let Some(node) = node {
111             if let Some(prop) = node.property("bootargs") {
112                 let bootargs = prop.as_str().unwrap();
113 
114                 boot_params()
115                     .write()
116                     .boot_cmdline_append(bootargs.as_bytes());
117             }
118         }
119 
120         // TODO: 拼接内核自定义的command line参数
121 
122         kdebug!("Command line: {}", boot_params().read().boot_cmdline_str());
123         return Ok(());
124     }
125 
126     /// 扫描 `/memory` 节点
127     ///
128     /// ## 参数
129     ///
130     /// - `fdt`:FDT
131     ///
132     /// ## 返回值
133     ///
134     /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。
135     fn early_init_scan_memory(&self, fdt: &Fdt) -> bool {
136         let mut found_memory = false;
137         for node in fdt.all_nodes() {
138             let device_type: Option<NodeProperty<'_>> = node.property("device_type");
139             if device_type.is_none() {
140                 continue;
141             }
142             let device_type = device_type.unwrap().as_str();
143             if device_type.is_none() || device_type.unwrap() != "memory" {
144                 continue;
145             }
146 
147             if !self.is_device_avaliable(&node) {
148                 continue;
149             }
150 
151             let reg = node.property("reg");
152             if reg.is_none() {
153                 continue;
154             }
155             let reg = reg.unwrap();
156             // 每个cell是4字节
157             let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
158             let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
159 
160             let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
161 
162             for i in 0..total_elements_in_reg {
163                 let mut base_index = i * (addr_cells + size_cells);
164                 let base: u64;
165                 let size: u64;
166                 match addr_cells {
167                     1 => {
168                         base = u32::from_be_bytes(
169                             reg.value[base_index..base_index + 4].try_into().unwrap(),
170                         ) as u64;
171                     }
172                     2 => {
173                         base = u64::from_be_bytes(
174                             reg.value[base_index..base_index + 8].try_into().unwrap(),
175                         );
176                     }
177                     _ => {
178                         panic!("addr_cells must be 1 or 2");
179                     }
180                 }
181                 base_index += addr_cells * 4;
182 
183                 match size_cells {
184                     1 => {
185                         size = u32::from_be_bytes(
186                             reg.value[base_index..base_index + 4].try_into().unwrap(),
187                         ) as u64;
188                     }
189                     2 => {
190                         size = u64::from_be_bytes(
191                             reg.value[base_index..base_index + 8].try_into().unwrap(),
192                         );
193                     }
194                     _ => {
195                         panic!("size_cells must be 1 or 2");
196                     }
197                 }
198 
199                 if size == 0 {
200                     continue;
201                 }
202 
203                 kdebug!("Found memory: base={:#x}, size={:#x}", base, size);
204                 self.early_init_dt_add_memory(base, size);
205                 found_memory = true;
206             }
207         }
208 
209         return found_memory;
210     }
211 
212     fn early_init_dt_add_memory(&self, base: u64, size: u64) {
213         let mut base = base as usize;
214         let mut size = size as usize;
215 
216         if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) {
217             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
218         }
219 
220         if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false {
221             size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK));
222             base = page_align_down(base);
223         }
224 
225         size = page_align_down(size);
226 
227         if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
228             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
229         }
230 
231         if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
232             kwarn!(
233                 "Ignoring memory range {:#x}-{:#x}",
234                 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1,
235                 base + size
236             );
237             size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1;
238         }
239 
240         if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
241             kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size);
242             return;
243         }
244 
245         if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
246             {
247                 kwarn!(
248                     "Ignoring memory range {:#x}-{:#x}",
249                     base,
250                     MemBlockManager::MIN_MEMBLOCK_ADDR.data()
251                 );
252                 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
253                 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
254             }
255 
256             mem_block_manager()
257                 .add_block(PhysAddr::new(base), size)
258                 .unwrap_or_else(|e| {
259                     panic!(
260                         "Failed to add memory block '{:#x}-{:#x}', err={:?}",
261                         base,
262                         base + size,
263                         e
264                     );
265                 });
266         }
267     }
268 
269     fn is_device_avaliable(&self, node: &FdtNode) -> bool {
270         let status = node.property("status");
271         if status.is_none() {
272             return true;
273         }
274 
275         let status = status.unwrap().as_str();
276         if let Some(status) = status {
277             if status == "okay" || status == "ok" {
278                 return true;
279             }
280         }
281 
282         return false;
283     }
284 
285     pub unsafe fn set_fdt_vaddr(&self, vaddr: VirtAddr) -> Result<(), SystemError> {
286         if vaddr.is_null() {
287             return Err(SystemError::EINVAL);
288         }
289         fdt::Fdt::from_ptr(vaddr.as_ptr()).map_err(|e| {
290             kerror!("failed to parse fdt, err={:?}", e);
291             SystemError::EINVAL
292         })?;
293 
294         unsafe {
295             FDT_VADDR = Some(vaddr);
296         }
297 
298         Ok(())
299     }
300 }
301