1 use core::mem::size_of;
2
3 use fdt::{
4 node::{FdtNode, NodeProperty},
5 Fdt,
6 };
7 use log::{debug, error, warn};
8 use system_error::SystemError;
9
10 use crate::{
11 init::boot_params,
12 libs::rwlock::RwLock,
13 mm::{memblock::mem_block_manager, mmio_buddy::MMIOSpaceGuard, PhysAddr},
14 };
15
16 static OPEN_FIRMWARE_FDT_DRIVER: OpenFirmwareFdtDriver = OpenFirmwareFdtDriver::new();
17
18 #[inline(always)]
open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver19 pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
20 &OPEN_FIRMWARE_FDT_DRIVER
21 }
22
23 static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new());
24
25 #[derive(Debug)]
26 struct FdtGlobalData {
27 /// FDT根节点下的`size-cells`属性值
28 root_size_cells: u32,
29
30 /// FDT根节点下的`address-cells`属性值
31 root_addr_cells: u32,
32
33 chosen_node_name: Option<&'static str>,
34 }
35
36 impl FdtGlobalData {
new() -> Self37 pub const fn new() -> Self {
38 Self {
39 root_size_cells: 1,
40 root_addr_cells: 1,
41 chosen_node_name: None,
42 }
43 }
44 }
45
46 #[allow(dead_code)]
47 pub struct OpenFirmwareFdtDriver {
48 inner: RwLock<InnerOpenFirmwareFdtDriver>,
49 }
50
51 #[allow(dead_code)]
52 pub struct InnerOpenFirmwareFdtDriver {
53 /// FDT自身映射的MMIO空间
54 fdt_map_guard: Option<MMIOSpaceGuard>,
55 }
56
57 impl OpenFirmwareFdtDriver {
new() -> Self58 const fn new() -> Self {
59 Self {
60 inner: RwLock::new(InnerOpenFirmwareFdtDriver {
61 fdt_map_guard: None,
62 }),
63 }
64 }
65
66 #[allow(dead_code)]
early_scan_device_tree(&self) -> Result<(), SystemError>67 pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
68 let fdt = self.fdt_ref()?;
69 self.early_init_scan_nodes(&fdt);
70
71 return Ok(());
72 }
73
set_fdt_map_guard(&self, guard: Option<MMIOSpaceGuard>)74 pub unsafe fn set_fdt_map_guard(&self, guard: Option<MMIOSpaceGuard>) {
75 self.inner.write().fdt_map_guard = guard;
76 }
77
78 /// 获取FDT的引用
fdt_ref(&self) -> Result<Fdt<'static>, SystemError>79 pub fn fdt_ref(&self) -> Result<Fdt<'static>, SystemError> {
80 let fdt_vaddr = boot_params().read().fdt().ok_or(SystemError::ENODEV)?;
81 let fdt: Fdt<'_> = unsafe {
82 fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
83 error!("failed to parse fdt, err={:?}", e);
84 SystemError::EINVAL
85 })
86 }?;
87 Ok(fdt)
88 }
89
early_init_scan_nodes(&self, fdt: &Fdt)90 fn early_init_scan_nodes(&self, fdt: &Fdt) {
91 self.early_init_scan_root(fdt)
92 .expect("Failed to scan fdt root node.");
93
94 self.early_init_scan_chosen(fdt).unwrap_or_else(|_| {
95 warn!("No `chosen` node found");
96 });
97
98 self.early_init_scan_memory(fdt);
99 }
100
101 /// 扫描根节点
early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError>102 fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> {
103 let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?;
104
105 let mut guard = FDT_GLOBAL_DATA.write();
106
107 if let Some(prop) = node.property("#size-cells") {
108 guard.root_size_cells = prop.as_usize().unwrap() as u32;
109
110 // debug!("fdt_root_size_cells={}", guard.root_size_cells);
111 }
112
113 if let Some(prop) = node.property("#address-cells") {
114 guard.root_addr_cells = prop.as_usize().unwrap() as u32;
115
116 // debug!("fdt_root_addr_cells={}", guard.root_addr_cells);
117 }
118
119 return Ok(());
120 }
121
122 /// 扫描 `/chosen` 节点
early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError>123 fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> {
124 const CHOSEN_NAME1: &str = "/chosen";
125 let mut node = fdt.find_node(CHOSEN_NAME1);
126 if node.is_none() {
127 const CHOSEN_NAME2: &str = "/chosen@0";
128 node = fdt.find_node(CHOSEN_NAME2);
129 if node.is_some() {
130 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2);
131 }
132 } else {
133 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1);
134 }
135
136 if let Some(node) = node {
137 if let Some(prop) = node.property("bootargs") {
138 let bootargs = prop.as_str().unwrap();
139
140 boot_params()
141 .write()
142 .boot_cmdline_append(bootargs.as_bytes());
143 }
144 }
145
146 // TODO: 拼接内核自定义的command line参数
147
148 debug!("Command line: {}", boot_params().read().boot_cmdline_str());
149 return Ok(());
150 }
151
152 /// 扫描 `/memory` 节点
153 ///
154 /// ## 参数
155 ///
156 /// - `fdt`:FDT
157 ///
158 /// ## 返回值
159 ///
160 /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。
early_init_scan_memory(&self, fdt: &Fdt) -> bool161 fn early_init_scan_memory(&self, fdt: &Fdt) -> bool {
162 let mut found_memory = false;
163 for node in fdt.all_nodes() {
164 let device_type: Option<NodeProperty<'_>> = node.property("device_type");
165 if device_type.is_none() {
166 continue;
167 }
168 let device_type = device_type.unwrap().as_str();
169 if device_type.is_none() || device_type.unwrap() != "memory" {
170 continue;
171 }
172
173 if !self.is_device_avaliable(&node) {
174 continue;
175 }
176
177 let reg = node.property("reg");
178 if reg.is_none() {
179 continue;
180 }
181 let reg = reg.unwrap();
182 // 每个cell是4字节
183 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
184 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
185
186 let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
187
188 for i in 0..total_elements_in_reg {
189 let base_index = i * (addr_cells + size_cells);
190
191 let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
192 let (size, _) = read_cell(reg.value, base_index, size_cells);
193
194 if size == 0 {
195 continue;
196 }
197
198 debug!("Found memory: base={:#x}, size={:#x}", base, size);
199 self.early_init_dt_add_memory(base, size);
200 found_memory = true;
201 }
202 }
203
204 return found_memory;
205 }
206
207 #[cfg(target_arch = "x86_64")]
early_init_dt_add_memory(&self, _base: u64, _size: u64)208 pub fn early_init_dt_add_memory(&self, _base: u64, _size: u64) {
209 panic!("x86_64 should not call early_init_dt_add_memory");
210 }
211
212 #[cfg(not(target_arch = "x86_64"))]
early_init_dt_add_memory(&self, base: u64, size: u64)213 pub fn early_init_dt_add_memory(&self, base: u64, size: u64) {
214 use crate::{
215 arch::MMArch,
216 libs::align::page_align_down,
217 mm::{memblock::MemBlockManager, MemoryManagementArch},
218 };
219
220 let mut base = base as usize;
221 let mut size = size as usize;
222
223 if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) {
224 warn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
225 }
226
227 if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false {
228 size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK));
229 base = page_align_down(base);
230 }
231
232 size = page_align_down(size);
233
234 if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
235 warn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
236 }
237
238 if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
239 warn!(
240 "Ignoring memory range {:#x}-{:#x}",
241 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1,
242 base + size
243 );
244 size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1;
245 }
246
247 if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
248 warn!("Ignoring memory range {:#x}-{:#x}", base, base + size);
249 return;
250 }
251
252 if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
253 {
254 warn!(
255 "Ignoring memory range {:#x}-{:#x}",
256 base,
257 MemBlockManager::MIN_MEMBLOCK_ADDR.data()
258 );
259 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
260 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
261 }
262 }
263
264 mem_block_manager()
265 .add_block(PhysAddr::new(base), size)
266 .unwrap_or_else(|e| {
267 panic!(
268 "Failed to add memory block '{:#x}-{:#x}', err={:?}",
269 base,
270 base + size,
271 e
272 );
273 });
274 }
275
276 /// 判断设备是否可用
is_device_avaliable(&self, node: &FdtNode) -> bool277 fn is_device_avaliable(&self, node: &FdtNode) -> bool {
278 let status = node.property("status");
279 if status.is_none() {
280 return true;
281 }
282
283 let status = status.unwrap().as_str();
284 if let Some(status) = status {
285 if status == "okay" || status == "ok" {
286 return true;
287 }
288 }
289
290 return false;
291 }
292
293 /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
294 ///
295 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
early_init_fdt_scan_reserved_mem(&self)296 pub fn early_init_fdt_scan_reserved_mem(&self) {
297 let vaddr = boot_params().read().fdt();
298 if vaddr.is_none() {
299 return;
300 }
301 let vaddr = vaddr.unwrap();
302 let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) };
303 if fdt.is_err() {
304 return;
305 }
306
307 let fdt = fdt.unwrap();
308 self.early_reserve_fdt_itself(&fdt);
309
310 let reserved_mem_nodes = fdt.memory_reservations();
311
312 for node in reserved_mem_nodes {
313 if node.size() != 0 {
314 let address = PhysAddr::new(node.address() as usize);
315 let size = node.size();
316 debug!("Reserve memory: {:?}-{:?}", address, address + size);
317 mem_block_manager().reserve_block(address, size).unwrap();
318 }
319 }
320
321 self.fdt_scan_reserved_mem(&fdt)
322 .expect("Failed to scan reserved memory");
323 }
324
325 /// 保留fdt自身的内存空间
326
early_reserve_fdt_itself(&self, fdt: &Fdt)327 fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
328 #[cfg(target_arch = "riscv64")]
329 {
330 use crate::libs::align::{page_align_down, page_align_up};
331
332 let fdt_paddr = boot_params().read().arch.fdt_paddr;
333 let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
334 let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
335 mem_block_manager()
336 .reserve_block(rsvd_start, rsvd_size)
337 .expect("Failed to reserve memory for fdt");
338 }
339
340 #[cfg(target_arch = "x86_64")]
341 {
342 let _ = fdt;
343 }
344 }
345
fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError>346 fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
347 let node = fdt
348 .find_node("/reserved-memory")
349 .ok_or(SystemError::ENODEV)?;
350
351 for child in node.children() {
352 if !self.is_device_avaliable(&child) {
353 continue;
354 }
355
356 reserved_mem_reserve_reg(&child).ok();
357 }
358
359 return Ok(());
360 }
361
early_init_dt_reserve_memory( &self, base: PhysAddr, size: usize, nomap: bool, ) -> Result<(), SystemError>362 fn early_init_dt_reserve_memory(
363 &self,
364 base: PhysAddr,
365 size: usize,
366 nomap: bool,
367 ) -> Result<(), SystemError> {
368 if nomap {
369 if mem_block_manager().is_overlapped(base, size)
370 && mem_block_manager().is_overlapped_with_reserved(base, size)
371 {
372 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
373 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
374 return Err(SystemError::EBUSY);
375 }
376
377 return mem_block_manager().mark_nomap(base, size);
378 }
379
380 return mem_block_manager().reserve_block(base, size);
381 }
382
find_node_by_compatible<'b>( &self, fdt: &'b Fdt<'b>, compatible: &'b str, ) -> impl Iterator<Item = fdt::node::FdtNode<'b, 'b>> + 'b383 pub fn find_node_by_compatible<'b>(
384 &self,
385 fdt: &'b Fdt<'b>,
386 compatible: &'b str,
387 ) -> impl Iterator<Item = fdt::node::FdtNode<'b, 'b>> + 'b {
388 // compatible = compatible.trim();
389 let r = fdt.all_nodes().filter(move |x| {
390 x.compatible()
391 .is_some_and(|x| x.all().any(|x| x == compatible))
392 });
393
394 return r;
395 }
396 }
397
398 #[allow(dead_code)]
reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError>399 fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
400 let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
401 FDT_GLOBAL_DATA.read();
402 let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
403 * size_of::<u32>();
404 drop(global_data_guard);
405
406 let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
407
408 let mut reg_size = reg.value.len();
409 if reg_size > 0 && reg_size % t_len != 0 {
410 error!(
411 "Reserved memory: invalid reg property in '{}', skipping node.",
412 node.name
413 );
414 return Err(SystemError::EINVAL);
415 }
416 // 每个cell是4字节
417 let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
418 let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
419
420 let nomap = node.property("no-map").is_some();
421
422 let mut base_index = 0;
423
424 while reg_size >= t_len {
425 let (base, bi) = read_cell(reg.value, base_index, addr_cells);
426 base_index = bi;
427 let (size, bi) = read_cell(reg.value, base_index, size_cells);
428 base_index = bi;
429
430 if size > 0
431 && open_firmware_fdt_driver()
432 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
433 .is_ok()
434 {
435 debug!(
436 "Reserved memory: base={:#x}, size={:#x}, nomap={}",
437 base, size, nomap
438 );
439 } else {
440 error!(
441 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
442 base, size, nomap
443 );
444 }
445
446 reg_size -= t_len;
447
448 // todo: linux这里保存了节点,但是我感觉现在还用不着。
449 }
450
451 return Ok(());
452 }
453
454 /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
455 ///
456 /// ## 参数
457 ///
458 /// - `reg_value`:`reg`属性数组的引用
459 /// - `base_index`:起始索引
460 /// - `cells`:要读取的cell数量,必须是1或2
461 ///
462 /// ## 返回值
463 ///
464 /// (value, next_base_index)
read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize)465 fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
466 let next_base_index = base_index + cells * 4;
467 match cells {
468 1 => {
469 return (
470 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
471 .into(),
472 next_base_index,
473 );
474 }
475
476 2 => {
477 return (
478 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
479 next_base_index,
480 );
481 }
482 _ => {
483 panic!("cells must be 1 or 2");
484 }
485 }
486 }
487