sparreal_kernel/platform/
fdt.rs

1use alloc::{
2    string::{String, ToString},
3    vec::Vec,
4};
5use arrayvec::ArrayVec;
6use core::{ops::Range, ptr::NonNull};
7use fdt_parser::{Node, Pci};
8use log::warn;
9use rdrive::Phandle;
10
11use super::{CPUInfo, SerialPort};
12use crate::mem::PhysAddr;
13use crate::{irq::IrqInfo, mem::mmu::LINER_OFFSET};
14
15#[derive(Clone)]
16pub struct Fdt(PhysAddr);
17
18impl Fdt {
19    pub fn new(addr: PhysAddr) -> Self {
20        Self(addr)
21    }
22
23    pub fn model_name(&self) -> Option<String> {
24        let fdt = self.get();
25        let node = fdt.all_nodes().next()?;
26
27        let model = node.find_property("model")?;
28
29        Some(model.str().to_string())
30    }
31
32    pub fn cpus(&self) -> Vec<CPUInfo> {
33        let fdt = self.get();
34
35        fdt.find_nodes("/cpus/cpu")
36            .filter(|n| n.name().starts_with("cpu@"))
37            .map(|cpu| {
38                let reg = cpu.reg().unwrap().next().unwrap();
39                CPUInfo {
40                    cpu_id: super::CPUHardId(reg.address as usize),
41                }
42            })
43            .collect()
44    }
45
46    pub fn get(&self) -> fdt_parser::Fdt<'static> {
47        fdt_parser::Fdt::from_ptr(self.get_addr()).unwrap()
48    }
49
50    pub fn get_addr(&self) -> NonNull<u8> {
51        NonNull::new((self.0 + LINER_OFFSET).raw() as _).unwrap()
52    }
53
54    pub fn memorys(&self) -> ArrayVec<Range<PhysAddr>, 12> {
55        let mut out = ArrayVec::new();
56
57        let fdt = self.get();
58
59        for node in fdt.memory() {
60            for region in node.regions() {
61                let addr = (region.address as usize).into();
62                out.push(addr..addr + region.size);
63            }
64        }
65        out
66    }
67
68    pub fn take_memory(&self) -> Range<PhysAddr> {
69        let region = self
70            .get()
71            .memory()
72            .next()
73            .unwrap()
74            .regions()
75            .next()
76            .unwrap();
77        let addr = (region.address as usize).into();
78        addr..addr + region.size
79    }
80
81    pub fn debugcon(&self) -> Option<SerialPort> {
82        let fdt = self.get();
83        let stdout = fdt.chosen()?.stdout()?;
84        let compatible = stdout.node.compatibles();
85        let reg = stdout.node.reg()?.next()?;
86        Some(SerialPort::new(
87            (reg.address as usize).into(),
88            reg.size,
89            compatible,
90        ))
91    }
92}
93
94pub trait GetIrqConfig {
95    fn irq_info(&self) -> Option<IrqInfo>;
96}
97
98impl GetIrqConfig for Node<'_> {
99    fn irq_info(&self) -> Option<IrqInfo> {
100        let irq_chip_node = self.interrupt_parent()?;
101        let phandle = irq_chip_node.node.phandle()?;
102
103        let interrupts = self.interrupts()?.map(|o| o.collect()).collect::<Vec<_>>();
104
105        parse_irq_config(phandle, &interrupts)
106    }
107}
108
109fn parse_irq_config(parent: Phandle, interrupts: &[Vec<u32>]) -> Option<IrqInfo> {
110    let irq_parent = rdrive::fdt_phandle_to_device_id(parent)?;
111    let parent = rdrive::get::<rdif_intc::Intc>(irq_parent).expect("Intc not found");
112    let parse_fun = { parent.lock().unwrap().parse_dtb_fn()? };
113
114    let mut cfgs = Vec::new();
115    for raw in interrupts {
116        if let Ok(v) = parse_fun(raw) {
117            cfgs.push(v);
118        } else {
119            warn!("Failed to parse IRQ config: {raw:?}");
120            continue;
121        }
122    }
123
124    Some(IrqInfo { irq_parent, cfgs })
125}
126
127pub trait GetPciIrqConfig {
128    fn child_irq_info(&self, bus: u8, device: u8, function: u8, irq_pin: u8) -> Option<IrqInfo>;
129}
130impl GetPciIrqConfig for Pci<'_> {
131    fn child_irq_info(&self, bus: u8, device: u8, func: u8, irq_pin: u8) -> Option<IrqInfo> {
132        let irq = self
133            .child_interrupts(bus, device, func, irq_pin as _)
134            .ok()?;
135
136        let raw = irq.irqs.collect::<Vec<_>>();
137
138        parse_irq_config(irq.parent, &[raw])
139    }
140}