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