fdt_edit/node/view/
mod.rs1mod clock;
9mod generic;
10mod intc;
11mod memory;
12mod pci;
13
14use core::fmt::Display;
15
16use alloc::{string::String, vec::Vec};
17use enum_dispatch::enum_dispatch;
18use fdt_raw::Phandle;
19
20use crate::{Fdt, Node, NodeId, Property, RangesEntry};
21
22pub use clock::{ClockNodeView, ClockNodeViewMut, ClockRef, ClockType, FixedClock};
24pub use generic::{NodeGeneric, NodeGenericMut};
25pub use intc::{IntcNodeView, IntcNodeViewMut};
26pub use memory::{MemoryNodeView, MemoryNodeViewMut};
27pub use pci::{PciInterruptInfo, PciInterruptMap, PciNodeView, PciNodeViewMut, PciRange, PciSpace};
28
29#[enum_dispatch]
30pub(crate) trait ViewOp<'a> {
31 fn as_view(&self) -> NodeView<'a>;
32 fn display(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33 self.as_view().fmt(f)
34 }
35}
36
37pub(crate) trait ViewMutOp<'a> {
38 fn new(node: NodeGenericMut<'a>) -> Self;
39}
40
41#[derive(Clone, Copy)]
50pub(crate) struct NodeView<'a> {
51 fdt: *mut Fdt,
52 id: NodeId,
53 _marker: core::marker::PhantomData<&'a ()>, }
55
56unsafe impl<'a> Send for NodeView<'a> {}
57
58impl<'a> NodeView<'a> {
59 pub(crate) fn new(fdt: &'a Fdt, id: NodeId) -> Self {
61 Self {
62 fdt: fdt as *const Fdt as *mut Fdt,
63 id,
64 _marker: core::marker::PhantomData,
65 }
66 }
67
68 pub fn name(&self) -> &'a str {
69 self.as_node().name()
70 }
71
72 pub fn id(&self) -> NodeId {
74 self.id
75 }
76
77 pub fn as_node(&self) -> &'a Node {
79 self.fdt()
80 .node(self.id)
81 .expect("NodeView references a valid node")
82 }
83
84 pub fn as_node_mut(&mut self) -> &'a mut Node {
85 self.fdt_mut()
86 .node_mut(self.id)
87 .expect("NodeViewMut references a valid node")
88 }
89
90 pub fn fdt(&self) -> &'a Fdt {
92 unsafe { &*self.fdt }
93 }
94
95 pub fn fdt_mut(&mut self) -> &'a mut Fdt {
96 unsafe { &mut *self.fdt }
97 }
98
99 pub fn path(&self) -> String {
100 self.fdt().path_of(self.id)
101 }
102
103 pub fn parent(&self) -> Option<NodeType<'a>> {
104 self.fdt()
105 .parent_of(self.id)
106 .map(|pid| NodeView::new(self.fdt(), pid).classify())
107 }
108
109 #[allow(dead_code)]
110 pub fn parent_mut(&mut self) -> Option<NodeTypeMut<'a>> {
111 let parent = self.fdt().parent_of(self.id)?;
112 let mut parent_view = NodeView::new(self.fdt(), parent);
113 let cl = parent_view.classify_mut();
114 Some(cl)
115 }
116
117 pub fn address_cells(&self) -> Option<u32> {
118 self.as_node().address_cells()
119 }
120
121 pub fn size_cells(&self) -> Option<u32> {
122 self.as_node().size_cells()
123 }
124
125 pub fn interrupt_parent(&self) -> Option<Phandle> {
127 let mut current = Some(self.id);
128
129 while let Some(node_id) = current {
130 let node = self.fdt().node(node_id)?;
131 if let Some(phandle) = node.interrupt_parent() {
132 return Some(phandle);
133 }
134 current = self.fdt().parent_of(node_id);
135 }
136
137 None
138 }
139
140 pub fn regs(&self) -> Vec<RegFixed> {
144 let node = self.as_node();
145 let reg = match node.get_property("reg") {
146 Some(p) => p,
147 None => return Vec::new(),
148 };
149
150 let (addr_cells, size_cells) = self.parent_cells();
152
153 let ranges = self.parent_ranges();
155
156 let mut reader = reg.as_reader();
157 let mut results = Vec::new();
158
159 while let Some(child_bus_address) = reader.read_cells(addr_cells) {
160 let size = if size_cells > 0 {
161 reader.read_cells(size_cells)
162 } else {
163 None
164 };
165
166 let mut address = child_bus_address;
168 if let Some(ref ranges) = ranges {
169 for r in ranges {
170 if child_bus_address >= r.child_bus_address
171 && child_bus_address < r.child_bus_address + r.length
172 {
173 address = child_bus_address - r.child_bus_address + r.parent_bus_address;
174 break;
175 }
176 }
177 }
178
179 results.push(RegFixed {
180 address,
181 child_bus_address,
182 size,
183 });
184 }
185
186 results
187 }
188
189 fn parent_cells(&self) -> (usize, usize) {
191 if let Some(parent) = self.parent() {
192 let ac = parent.as_view().address_cells().unwrap_or(2) as usize;
193 let sc = parent.as_view().size_cells().unwrap_or(1) as usize;
194 (ac, sc)
195 } else {
196 (2, 1)
197 }
198 }
199
200 fn parent_ranges(&self) -> Option<Vec<RangesEntry>> {
202 self.parent().and_then(|p| {
203 let view = p.as_view();
204 let parent_addr_cells = p
206 .parent()
207 .and_then(|gp| gp.as_view().address_cells())
208 .unwrap_or(2);
209 view.as_node().ranges(parent_addr_cells)
210 })
211 }
212
213 pub fn set_regs(&mut self, regs: &[fdt_raw::RegInfo]) {
218 let (addr_cells, size_cells) = self.parent_cells();
220
221 let ranges = self.parent_ranges();
223
224 let mut data = Vec::new();
225
226 for reg in regs {
227 let mut bus_address = reg.address;
229 if let Some(ref ranges) = ranges {
230 for r in ranges {
231 if reg.address >= r.parent_bus_address
233 && reg.address < r.parent_bus_address + r.length
234 {
235 bus_address = reg.address - r.parent_bus_address + r.child_bus_address;
237 break;
238 }
239 }
240 }
241
242 match addr_cells {
244 1 => data.extend_from_slice(&(bus_address as u32).to_be_bytes()),
245 2 => {
246 data.extend_from_slice(&((bus_address >> 32) as u32).to_be_bytes());
247 data.extend_from_slice(&((bus_address & 0xFFFF_FFFF) as u32).to_be_bytes());
248 }
249 n => {
250 for i in 0..n {
252 let shift = (n - 1 - i) * 32;
253 data.extend_from_slice(&(((bus_address >> shift) as u32).to_be_bytes()));
254 }
255 }
256 }
257
258 let size = reg.size.unwrap_or(0);
260 match size_cells {
261 1 => data.extend_from_slice(&(size as u32).to_be_bytes()),
262 2 => {
263 data.extend_from_slice(&((size >> 32) as u32).to_be_bytes());
264 data.extend_from_slice(&((size & 0xFFFF_FFFF) as u32).to_be_bytes());
265 }
266 n => {
267 for i in 0..n {
268 let shift = (n - 1 - i) * 32;
269 data.extend_from_slice(&(((size >> shift) as u32).to_be_bytes()));
270 }
271 }
272 }
273 }
274
275 let prop = Property::new("reg", data);
276 self.as_node_mut().set_property(prop);
277 }
278
279 pub(crate) fn classify(&self) -> NodeType<'a> {
280 if let Some(node) = ClockNodeView::try_from_view(*self) {
281 return NodeType::Clock(node);
282 }
283
284 if let Some(node) = PciNodeView::try_from_view(*self) {
285 return NodeType::Pci(node);
286 }
287
288 if let Some(node) = MemoryNodeView::try_from_view(*self) {
289 return NodeType::Memory(node);
290 }
291
292 if let Some(node) = IntcNodeView::try_from_view(*self) {
293 return NodeType::InterruptController(node);
294 }
295
296 NodeType::Generic(NodeGeneric { inner: *self })
297 }
298
299 pub(crate) fn classify_mut(&mut self) -> NodeTypeMut<'a> {
300 if let Some(node) = ClockNodeViewMut::try_from_view(*self) {
301 return NodeTypeMut::Clock(node);
302 }
303
304 if let Some(node) = PciNodeViewMut::try_from_view(*self) {
305 return NodeTypeMut::Pci(node);
306 }
307
308 if let Some(node) = MemoryNodeViewMut::try_from_view(*self) {
309 return NodeTypeMut::Memory(node);
310 }
311
312 if let Some(node) = IntcNodeViewMut::try_from_view(*self) {
313 return NodeTypeMut::InterruptController(node);
314 }
315
316 NodeTypeMut::Generic(NodeGenericMut { inner: *self })
317 }
318}
319
320impl core::fmt::Display for NodeView<'_> {
321 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
322 write!(f, "{}", self.path())?;
323 for prop in self.as_node().properties() {
324 write!(f, "\n {} = ", prop.name())?;
325 if prop.name() == "compatible" {
326 write!(f, "[")?;
327 let strs: Vec<&str> = prop.as_str_iter().collect();
328 for (i, s) in strs.iter().enumerate() {
329 write!(f, "\"{}\"", s)?;
330 if i < strs.len() - 1 {
331 write!(f, ", ")?;
332 }
333 }
334 write!(f, "]")?;
335 continue;
336 }
337 if let Some(s) = prop.as_str() {
338 write!(f, "\"{}\";", s)?;
339 } else {
340 for cell in prop.get_u32_iter() {
341 write!(f, "{:#x} ", cell)?;
342 }
343 write!(f, ";")?;
344 }
345 }
346 Ok(())
347 }
348}
349
350#[enum_dispatch(ViewOp)]
355pub enum NodeType<'a> {
357 Clock(ClockNodeView<'a>),
359 Memory(MemoryNodeView<'a>),
361 InterruptController(IntcNodeView<'a>),
363 Pci(PciNodeView<'a>),
365 Generic(NodeGeneric<'a>),
367}
368
369impl<'a> NodeType<'a> {
370 pub fn as_node(&self) -> &'a Node {
372 self.as_view().as_node()
373 }
374
375 pub fn path(&self) -> String {
377 self.as_view().path()
378 }
379
380 pub fn parent(&self) -> Option<NodeType<'a>> {
381 self.as_view().parent()
382 }
383
384 pub fn id(&self) -> NodeId {
386 self.as_view().id()
387 }
388
389 pub fn name(&self) -> &'a str {
391 self.as_view().name()
392 }
393
394 pub fn regs(&self) -> Vec<RegFixed> {
396 self.as_view().regs()
397 }
398
399 pub fn interrupt_parent(&self) -> Option<Phandle> {
401 self.as_view().interrupt_parent()
402 }
403}
404
405impl core::fmt::Display for NodeType<'_> {
406 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407 self.display(f)
408 }
409}
410
411#[enum_dispatch(ViewOp)]
417pub enum NodeTypeMut<'a> {
418 Clock(ClockNodeViewMut<'a>),
419 Memory(MemoryNodeViewMut<'a>),
420 InterruptController(IntcNodeViewMut<'a>),
421 Pci(PciNodeViewMut<'a>),
422 Generic(NodeGenericMut<'a>),
423}
424
425impl<'a> NodeTypeMut<'a> {
426 pub fn id(&self) -> NodeId {
428 self.as_view().id()
429 }
430
431 pub fn set_regs(&mut self, regs: &[fdt_raw::RegInfo]) {
436 self.as_view().set_regs(regs);
437 }
438}
439
440impl Fdt {
445 fn view(&self, id: NodeId) -> Option<NodeView<'_>> {
447 if self.node(id).is_some() {
448 Some(NodeView::new(self, id))
449 } else {
450 None
451 }
452 }
453
454 pub fn view_typed(&self, id: NodeId) -> Option<NodeType<'_>> {
456 self.view(id).map(|v| v.classify())
457 }
458
459 pub fn view_typed_mut(&mut self, id: NodeId) -> Option<NodeTypeMut<'_>> {
461 self.view(id).map(|mut v| v.classify_mut())
462 }
463}
464
465impl<'a> NodeGenericMut<'a> {
466 pub fn add_child_memory(&mut self, name: &str) -> MemoryNodeViewMut<'a> {
467 self.add_child(name)
468 }
469
470 pub fn add_child_interrupt_controller(&mut self, name: &str) -> IntcNodeViewMut<'a> {
471 self.add_child(name)
472 }
473}
474
475#[derive(Clone, Copy, Debug)]
476pub struct RegFixed {
477 pub address: u64,
478 pub child_bus_address: u64,
479 pub size: Option<u64>,
480}