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