fdt_parser/cache/node/
mod.rs1use core::{fmt::Debug, ops::Deref};
2
3use super::Fdt;
4use crate::{
5 base::{self, RegIter},
6 data::{Raw, U32Iter2D},
7 property::PropIter,
8 FdtError, FdtRangeSilce, FdtReg, Phandle, Property, Status,
9};
10
11use alloc::{
12 string::{String, ToString},
13 vec::Vec,
14};
15
16mod chosen;
17mod clock;
18mod interrupt_controller;
19mod memory;
20mod pci;
21
22pub use chosen::*;
23pub use clock::*;
24pub use interrupt_controller::*;
25pub use memory::*;
26pub use pci::*;
27
28#[derive(Debug, Clone)]
29pub enum Node {
30 General(NodeBase),
31 Chosen(Chosen),
32 Memory(Memory),
33 InterruptController(InterruptController),
34 Pci(Pci),
35}
36
37impl Node {
38 pub(super) fn new(fdt: &Fdt, meta: &NodeMeta) -> Self {
39 let base = NodeBase {
40 fdt: fdt.clone(),
41 meta: meta.clone(),
42 };
43
44 match meta.name.as_str() {
46 "chosen" => Self::Chosen(Chosen::new(base)),
47 name if name.starts_with("memory@") => Self::Memory(Memory::new(base)),
48 _ => {
49 let pci = Pci::new(base.clone());
51 if pci.is_pci_host_bridge() {
52 Self::Pci(pci)
53 } else if base.is_interrupt_controller() {
54 Self::InterruptController(InterruptController::new(base))
55 } else {
56 Self::General(base)
57 }
58 }
59 }
60 }
61}
62
63impl Deref for Node {
64 type Target = NodeBase;
65
66 fn deref(&self) -> &Self::Target {
67 match self {
68 Node::General(n) => n,
69 Node::Chosen(n) => n,
70 Node::Memory(n) => n,
71 Node::InterruptController(n) => n,
72 Node::Pci(n) => n,
73 }
74 }
75}
76
77#[derive(Clone)]
78pub struct NodeBase {
79 fdt: Fdt,
80 meta: NodeMeta,
81}
82
83impl NodeBase {
84 fn raw<'a>(&'a self) -> Raw<'a> {
85 self.fdt.raw().begin_at(self.meta.pos)
86 }
87
88 pub fn level(&self) -> usize {
89 self.meta.level
90 }
91
92 pub fn name(&self) -> &str {
93 &self.meta.name
94 }
95
96 pub fn full_path(&self) -> &str {
97 &self.meta.full_path
98 }
99
100 pub fn parent(&self) -> Option<Node> {
101 let parent_path = self.meta.parent.as_ref()?.path.as_str();
102 let parent_meta = self.fdt.inner.get_node_by_path(parent_path)?;
103 Some(Node::new(&self.fdt, &parent_meta))
104 }
105
106 pub fn properties<'a>(&'a self) -> Vec<Property<'a>> {
107 let reader = self.raw().buffer();
108 PropIter::new(self.fdt.fdt_base(), reader)
109 .flatten()
110 .collect()
111 }
112
113 pub fn find_property<'a>(&'a self, name: impl AsRef<str>) -> Option<Property<'a>> {
114 self.properties()
115 .into_iter()
116 .find(|prop| prop.name == name.as_ref())
117 }
118
119 pub fn compatibles(&self) -> Vec<String> {
121 self.find_property("compatible")
122 .map(|p| {
123 p.str_list()
124 .filter(|s| !s.is_empty())
125 .map(|s| s.into())
126 .collect()
127 })
128 .unwrap_or_default()
129 }
130
131 pub fn status(&self) -> Option<Status> {
133 self.find_property("status")
134 .and_then(|prop| prop.str().ok())
135 .and_then(|s| {
136 if s.contains("disabled") {
137 Some(Status::Disabled)
138 } else if s.contains("okay") {
139 Some(Status::Okay)
140 } else {
141 None
142 }
143 })
144 }
145
146 pub fn address_cells(&self) -> u8 {
147 self.find_property("#address-cells")
148 .and_then(|p| p.u32().ok())
149 .map(|v| v as u8)
150 .or_else(|| {
151 self.meta
152 .parent
153 .as_ref()
154 .and_then(|info| info.address_cells)
155 })
156 .unwrap_or(2)
157 }
158
159 fn is_interrupt_controller(&self) -> bool {
160 self.name().starts_with("interrupt-controller")
161 || self.find_property("interrupt-controller").is_some()
162 || self.find_property("#interrupt-controller").is_some()
163 }
164
165 pub fn reg(&self) -> Result<Vec<FdtReg>, FdtError> {
167 let prop = self.find_property("reg").ok_or(FdtError::NotFound)?;
168
169 let parent_info = self
171 .meta
172 .parent
173 .as_ref()
174 .ok_or(FdtError::NodeNotFound("parent"))?;
175
176 let address_cell = parent_info.address_cells.unwrap_or(2);
178 let size_cell = parent_info.size_cells.unwrap_or(1);
179
180 let parent = self.parent().ok_or(FdtError::NodeNotFound("parent"))?;
181 let ranges = parent.ranges();
182 let iter = RegIter {
183 size_cell,
184 address_cell,
185 buff: prop.data.buffer(),
186 ranges,
187 };
188
189 Ok(iter.collect())
190 }
191
192 pub fn ranges(&self) -> Option<FdtRangeSilce<'_>> {
193 let p = self.find_property("ranges")?;
194 let parent_info = self.meta.parent.as_ref();
195
196 let address_cell = self
197 .find_property("#address-cells")
198 .and_then(|prop| prop.u32().ok())
199 .map(|v| v as u8)
200 .or_else(|| parent_info.and_then(|info| info.address_cells))
201 .unwrap_or(2);
202
203 let size_cell = self
204 .find_property("#size-cells")
205 .and_then(|prop| prop.u32().ok())
206 .map(|v| v as u8)
207 .or_else(|| parent_info.and_then(|info| info.size_cells))
208 .unwrap_or(1);
209
210 let address_cell_parent = parent_info.and_then(|info| info.address_cells).unwrap_or(2);
211
212 Some(FdtRangeSilce::new(
213 address_cell,
214 address_cell_parent,
215 size_cell,
216 &p.data,
217 ))
218 }
219
220 pub fn interrupt_parent_phandle(&self) -> Option<Phandle> {
221 self.meta.interrupt_parent
222 }
223
224 pub fn interrupt_parent(&self) -> Option<InterruptController> {
225 let phandle = self.interrupt_parent_phandle()?;
226 let irq = self.fdt.get_node_by_phandle(phandle)?;
227 let Node::InterruptController(i) = irq else {
228 return None;
229 };
230 Some(i)
231 }
232
233 pub fn interrupts(&self) -> Result<Vec<Vec<u32>>, FdtError> {
234 let res = self
235 .find_property("interrupts")
236 .ok_or(FdtError::PropertyNotFound("interrupts"))?;
237 let parent = self
238 .interrupt_parent()
239 .ok_or(FdtError::PropertyNotFound("interrupt-parent"))?;
240 let cells = parent.interrupt_cells()?;
241 let mut iter = U32Iter2D::new(&res.data, cells as _);
242 let mut out = Vec::new();
243 while let Some(entry) = iter.next() {
244 out.push(entry.collect());
245 }
246 Ok(out)
247 }
248
249 pub fn clocks(&self) -> Result<Vec<ClockInfo>, FdtError> {
251 let mut clocks = Vec::new();
252 let Some(prop) = self.find_property("clocks") else {
253 return Ok(clocks);
254 };
255
256 let mut data = prop.data.buffer();
257 let clock_names: Vec<String> = self
258 .find_property("clock-names")
259 .map(|p| p.str_list().map(|s| s.to_string()).collect())
260 .unwrap_or_else(Vec::new);
261
262 let mut index = 0usize;
263 while !data.remain().as_ref().is_empty() {
264 let phandle_raw = data.take_u32()?;
265 let phandle = Phandle::from(phandle_raw);
266
267 let provider = self
268 .fdt
269 .get_node_by_phandle(phandle)
270 .ok_or(FdtError::NodeNotFound("clock"))?;
271
272 let provider_node = provider.deref().clone();
273 let clock_cells = provider_node
274 .find_property("#clock-cells")
275 .and_then(|p| p.u32().ok())
276 .unwrap_or(0);
277 let select = if clock_cells > 0 {
278 data.take_by_cell_size(clock_cells as _)
279 .ok_or(FdtError::BufferTooSmall { pos: data.pos() })?
280 } else {
281 0
282 };
283
284 let provider = ClockType::new(provider_node);
285 let provider_output_name = provider.output_name(select);
286 let name = clock_names.get(index).cloned();
287
288 clocks.push(ClockInfo {
289 name,
290 provider_output_name,
291 provider,
292 phandle,
293 select,
294 });
295
296 index += 1;
297 }
298
299 Ok(clocks)
300 }
301}
302
303impl Debug for NodeBase {
304 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
305 let mut st = f.debug_struct("NodeBase");
306 st.finish()
308 }
309}
310
311#[derive(Clone)]
312pub(super) struct NodeMeta {
313 name: String,
314 full_path: String,
315 pos: usize,
316 pub level: usize,
317 interrupt_parent: Option<Phandle>,
318 parent: Option<ParentInfo>,
319}
320
321impl NodeMeta {
322 pub fn new(node: &base::Node<'_>, full_path: String, parent: Option<&NodeMeta>) -> Self {
323 NodeMeta {
324 full_path,
325 name: node.name().into(),
326 pos: node.raw.pos(),
327 level: node.level(),
328 interrupt_parent: node.get_interrupt_parent_phandle(),
329 parent: node.parent.as_ref().map(|p| ParentInfo {
330 path: parent.map(|n| n.full_path.clone()).unwrap_or_default(),
331 address_cells: p.address_cells,
332 size_cells: p.size_cells,
333 }),
334 }
335 }
336}
337
338#[derive(Clone)]
339struct ParentInfo {
340 path: String,
341 address_cells: Option<u8>,
342 size_cells: Option<u8>,
343}