1use alloc::{collections::BTreeMap, string::String, vec::Vec};
2
3use fdt_raw::{Phandle, Status};
4
5use crate::{Node, RangesEntry};
6
7#[derive(Clone, Default)]
13pub struct Context<'a> {
14 pub parents: Vec<&'a Node>,
17
18 pub phandle_map: BTreeMap<Phandle, &'a Node>,
21}
22
23impl<'a> Context<'a> {
24 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn current_path(&self) -> String {
30 self.parents
31 .iter()
32 .map(|n| n.name())
33 .collect::<Vec<_>>()
34 .join("/")
35 }
36
37 pub fn for_root() -> Self {
39 Self::default()
40 }
41
42 pub fn depth(&self) -> usize {
44 self.parents.len() + 1
45 }
46
47 pub fn parent(&self) -> Option<&'a Node> {
49 self.parents.last().copied()
50 }
51
52 pub fn parent_address_cells(&self) -> u32 {
55 self.parent().and_then(|p| p.address_cells()).unwrap_or(2)
56 }
57
58 pub fn parent_size_cells(&self) -> u32 {
61 self.parent().and_then(|p| p.size_cells()).unwrap_or(1)
62 }
63
64 pub fn interrupt_parent(&self) -> Option<Phandle> {
67 for parent in self.parents.iter().rev() {
68 if let Some(phandle) = parent.interrupt_parent() {
69 return Some(phandle);
70 }
71 }
72 None
73 }
74
75 pub fn is_disabled(&self) -> bool {
78 for parent in &self.parents {
79 if matches!(parent.status(), Some(Status::Disabled)) {
80 return true;
81 }
82 }
83 false
84 }
85
86 pub fn collect_ranges(&self) -> Vec<Vec<RangesEntry>> {
89 let mut ranges_stack = Vec::new();
90 let mut prev_address_cells = 2; for parent in &self.parents {
93 if let Some(ranges) = parent.ranges(prev_address_cells) {
94 ranges_stack.push(ranges);
95 }
96 prev_address_cells = parent.address_cells().unwrap_or(2);
98 }
99
100 ranges_stack
101 }
102
103 pub fn current_ranges(&self) -> Option<Vec<RangesEntry>> {
105 if self.parents.is_empty() {
107 return None;
108 }
109
110 let parent = self.parents.last()?;
111
112 let grandparent_address_cells = if self.parents.len() >= 2 {
114 self.parents[self.parents.len() - 2]
115 .address_cells()
116 .unwrap_or(2)
117 } else {
118 2 };
120 parent.ranges(grandparent_address_cells)
121 }
122
123 pub fn push(&mut self, node: &'a Node) {
124 self.parents.push(node);
125 }
126
127 pub fn find_by_phandle(&self, phandle: Phandle) -> Option<&'a Node> {
129 self.phandle_map.get(&phandle).copied()
130 }
131
132 pub fn build_phandle_map_from_node(node: &'a Node, map: &mut BTreeMap<Phandle, &'a Node>) {
134 if let Some(phandle) = node.phandle() {
135 map.insert(phandle, node);
136 }
137 for child in &node.children {
138 Self::build_phandle_map_from_node(child, map);
139 }
140 }
141}