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