fdt_parser/base/node/
chosen.rs1use core::{fmt::Debug, ops::Deref};
2
3use crate::{base::NodeBase, FdtError};
4
5#[derive(Clone, Debug)]
6pub enum DebugCon<'a> {
7 Node(NodeBase<'a>),
9 EarlyConInfo {
11 name: &'a str,
12 mmio: u64,
13 params: Option<&'a str>,
14 },
15}
16
17#[derive(Clone)]
18pub struct Chosen<'a> {
19 node: NodeBase<'a>,
20}
21
22impl<'a> Chosen<'a> {
23 pub(crate) fn new(node: NodeBase<'a>) -> Self {
24 Chosen { node }
25 }
26
27 pub fn bootargs(&self) -> Result<&'a str, FdtError> {
29 let prop = self.node.find_property("bootargs")?;
30 prop.str()
31 }
32
33 pub fn stdout(&self) -> Result<Stdout<'a>, FdtError> {
36 let prop = self.node.find_property("stdout-path")?;
37
38 let path = prop.str()?;
39
40 let mut sp = path.split(':');
41
42 let name = none_ok!(sp.next(), FdtError::NodeNotFound("path"));
43
44 let params = sp.next();
45 let node = self
46 .node
47 .fdt
48 .find_nodes(name)
49 .next()
50 .ok_or(FdtError::NodeNotFound("path"))??;
51
52 Ok(Stdout {
53 params,
54 node: node.deref().clone(),
55 })
56 }
57
58 pub fn debugcon(&self) -> Result<DebugCon<'a>, FdtError> {
59 match self.stdout() {
60 Ok(stdout) => Ok(DebugCon::Node(stdout.node.clone())),
61 Err(FdtError::NotFound) | Err(FdtError::NodeNotFound(_)) => {
62 self.fdt_bootargs_find_debugcon_info()
63 }
64 Err(e) => Err(e),
65 }
66 }
67
68 fn fdt_bootargs_find_debugcon_info(&self) -> Result<DebugCon<'a>, FdtError> {
69 let bootargs = self.bootargs()?;
70
71 let earlycon = none_ok!(bootargs
72 .split_ascii_whitespace()
73 .find(|&arg| arg.contains("earlycon")));
74
75 let mut tmp = earlycon.split('=');
76 let _ = none_ok!(tmp.next(), FdtError::NotFound);
77 let values = none_ok!(tmp.next(), FdtError::NotFound);
78
79 let mut params_iter = values.split(',');
81 let name = none_ok!(params_iter.next(), FdtError::NotFound);
82
83 if !name.contains("uart") {
84 return Err(FdtError::NotFound);
85 }
86
87 let param2 = none_ok!(params_iter.next(), FdtError::NotFound);
88
89 let addr_str = if param2.contains("0x") {
90 param2
91 } else {
92 none_ok!(params_iter.next(), FdtError::NotFound)
93 };
94
95 let mmio = u64::from_str_radix(addr_str.trim_start_matches("0x"), 16)
96 .map_err(|_| FdtError::Utf8Parse)?;
97
98 for node_result in self.node.fdt.all_nodes() {
100 let node = node_result?;
101 match node.reg() {
102 Ok(mut regs) => {
103 for reg in &mut regs {
104 if reg.address == mmio {
105 return Ok(DebugCon::Node(node.node().clone()));
106 }
107 }
108 }
109 Err(FdtError::NotFound) => {}
110 Err(e) => return Err(e),
111 }
112 }
113
114 let mut parts = values.split(',');
117 let _name = parts.next(); let _addr_part = parts.next(); let params = if let Some(param) = parts.next() {
120 let param_start = values.find(param).unwrap_or(0);
122 if param_start > 0 {
123 Some(&values[param_start..])
124 } else {
125 Some(param)
126 }
127 } else {
128 None
129 };
130
131 Ok(DebugCon::EarlyConInfo { name, mmio, params })
132 }
133}
134
135impl Debug for Chosen<'_> {
136 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137 f.debug_struct("Chosen")
138 .field("bootargs", &self.bootargs())
139 .field("stdout", &self.stdout())
140 .finish()
141 }
142}
143
144impl<'a> Deref for Chosen<'a> {
145 type Target = NodeBase<'a>;
146
147 fn deref(&self) -> &Self::Target {
148 &self.node
149 }
150}
151
152#[derive(Clone)]
153pub struct Stdout<'a> {
154 pub params: Option<&'a str>,
155 pub node: NodeBase<'a>,
156}
157
158impl<'a> Stdout<'a> {}
159
160impl Debug for Stdout<'_> {
161 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162 f.debug_struct("Stdout")
163 .field("name", &self.node.name())
164 .field("params", &self.params)
165 .finish()
166 }
167}
168
169impl<'a> Deref for Stdout<'a> {
170 type Target = NodeBase<'a>;
171
172 fn deref(&self) -> &Self::Target {
173 &self.node
174 }
175}