node.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. // This Source Code Form is subject to the terms of the Mozilla Public License,
  2. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  3. // obtain one at https://mozilla.org/MPL/2.0/.
  4. use crate::{
  5. parsing::{BigEndianU32, BigEndianU64, CStr, FdtData},
  6. standard_nodes::{Compatible, MemoryRegion},
  7. Fdt,
  8. };
  9. const FDT_BEGIN_NODE: u32 = 1;
  10. const FDT_END_NODE: u32 = 2;
  11. const FDT_PROP: u32 = 3;
  12. pub(crate) const FDT_NOP: u32 = 4;
  13. const FDT_END: u32 = 5;
  14. #[derive(Debug, Clone, Copy)]
  15. #[repr(C)]
  16. struct FdtProperty {
  17. len: BigEndianU32,
  18. name_offset: BigEndianU32,
  19. }
  20. impl FdtProperty {
  21. fn from_bytes(bytes: &mut FdtData<'_>) -> Option<Self> {
  22. let len = bytes.u32()?;
  23. let name_offset = bytes.u32()?;
  24. Some(Self { len, name_offset })
  25. }
  26. }
  27. /// A devicetree node
  28. #[derive(Debug, Clone, Copy)]
  29. pub struct FdtNode<'b, 'a: 'b> {
  30. pub name: &'a str,
  31. pub(crate) header: &'b Fdt<'a>,
  32. props: &'a [u8],
  33. parent_props: Option<&'a [u8]>,
  34. }
  35. impl<'b, 'a: 'b> FdtNode<'b, 'a> {
  36. fn new(
  37. name: &'a str,
  38. header: &'b Fdt<'a>,
  39. props: &'a [u8],
  40. parent_props: Option<&'a [u8]>,
  41. ) -> Self {
  42. Self { name, header, props, parent_props }
  43. }
  44. /// Returns an iterator over the available properties of the node
  45. pub fn properties(self) -> impl Iterator<Item = NodeProperty<'a>> + 'b {
  46. let mut stream = FdtData::new(self.props);
  47. let mut done = false;
  48. core::iter::from_fn(move || {
  49. if stream.is_empty() || done {
  50. return None;
  51. }
  52. while stream.peek_u32()?.get() == FDT_NOP {
  53. stream.skip(4);
  54. }
  55. if stream.peek_u32().unwrap().get() == FDT_PROP {
  56. Some(NodeProperty::parse(&mut stream, self.header))
  57. } else {
  58. done = true;
  59. None
  60. }
  61. })
  62. }
  63. /// Attempts to find the a property by its name
  64. pub fn property(self, name: &str) -> Option<NodeProperty<'a>> {
  65. self.properties().find(|p| p.name == name)
  66. }
  67. /// Returns an iterator over the children of the current node
  68. pub fn children(self) -> impl Iterator<Item = FdtNode<'b, 'a>> {
  69. let mut stream = FdtData::new(self.props);
  70. while stream.peek_u32().unwrap().get() == FDT_NOP {
  71. stream.skip(4);
  72. }
  73. while stream.peek_u32().unwrap().get() == FDT_PROP {
  74. NodeProperty::parse(&mut stream, self.header);
  75. }
  76. let mut done = false;
  77. core::iter::from_fn(move || {
  78. if stream.is_empty() || done {
  79. return None;
  80. }
  81. while stream.peek_u32()?.get() == FDT_NOP {
  82. stream.skip(4);
  83. }
  84. if stream.peek_u32()?.get() == FDT_BEGIN_NODE {
  85. let origin = stream.remaining();
  86. let ret = {
  87. stream.skip(4);
  88. let unit_name = CStr::new(stream.remaining()).expect("unit name").as_str()?;
  89. let full_name_len = unit_name.len() + 1;
  90. stream.skip(full_name_len);
  91. if full_name_len % 4 != 0 {
  92. stream.skip(4 - (full_name_len % 4));
  93. }
  94. Some(Self::new(unit_name, self.header, stream.remaining(), Some(self.props)))
  95. };
  96. stream = FdtData::new(origin);
  97. skip_current_node(&mut stream, self.header);
  98. ret
  99. } else {
  100. done = true;
  101. None
  102. }
  103. })
  104. }
  105. /// `reg` property
  106. ///
  107. /// Important: this method assumes that the value(s) inside the `reg`
  108. /// property represent CPU-addressable addresses that are able to fit within
  109. /// the platform's pointer size (e.g. `#address-cells` and `#size-cells` are
  110. /// less than or equal to 2 for a 64-bit platform). If this is not the case
  111. /// or you're unsure of whether this applies to the node, it is recommended
  112. /// to use the [`FdtNode::property`] method to extract the raw value slice
  113. /// or use the provided [`FdtNode::raw_reg`] helper method to give you an
  114. /// iterator over the address and size slices. One example of where this
  115. /// would return `None` for a node is a `pci` child node which contains the
  116. /// PCI address information in the `reg` property, of which the address has
  117. /// an `#address-cells` value of 3.
  118. pub fn reg(self) -> Option<impl Iterator<Item = crate::MemoryRegion> + 'a> {
  119. let sizes = self.parent_cell_sizes();
  120. if sizes.address_cells > 2 || sizes.size_cells > 2 {
  121. return None;
  122. }
  123. let mut reg = None;
  124. for prop in self.properties() {
  125. if prop.name == "reg" {
  126. let mut stream = FdtData::new(prop.value);
  127. reg = Some(core::iter::from_fn(move || {
  128. let starting_address = match sizes.address_cells {
  129. 1 => stream.u32()?.get() as usize,
  130. 2 => stream.u64()?.get() as usize,
  131. _ => return None,
  132. } as *const u8;
  133. let size = match sizes.size_cells {
  134. 0 => None,
  135. 1 => Some(stream.u32()?.get() as usize),
  136. 2 => Some(stream.u64()?.get() as usize),
  137. _ => return None,
  138. };
  139. Some(MemoryRegion { starting_address, size })
  140. }));
  141. break;
  142. }
  143. }
  144. reg
  145. }
  146. /// Convenience method that provides an iterator over the raw bytes for the
  147. /// address and size values inside of the `reg` property
  148. pub fn raw_reg(self) -> Option<impl Iterator<Item = RawReg<'a>> + 'a> {
  149. let sizes = self.parent_cell_sizes();
  150. if let Some(prop) = self.property("reg") {
  151. let mut stream = FdtData::new(prop.value);
  152. return Some(core::iter::from_fn(move || {
  153. Some(RawReg {
  154. address: stream.take(sizes.address_cells * 4)?,
  155. size: stream.take(sizes.size_cells * 4)?,
  156. })
  157. }));
  158. }
  159. None
  160. }
  161. /// `compatible` property
  162. pub fn compatible(self) -> Option<Compatible<'a>> {
  163. let mut s = None;
  164. for prop in self.properties() {
  165. if prop.name == "compatible" {
  166. s = Some(Compatible { data: prop.value });
  167. }
  168. }
  169. s
  170. }
  171. /// Cell sizes for child nodes
  172. pub fn cell_sizes(self) -> CellSizes {
  173. let mut cell_sizes = CellSizes::default();
  174. for property in self.properties() {
  175. match property.name {
  176. "#address-cells" => {
  177. cell_sizes.address_cells = BigEndianU32::from_bytes(property.value)
  178. .expect("not enough bytes for #address-cells value")
  179. .get() as usize;
  180. }
  181. "#size-cells" => {
  182. cell_sizes.size_cells = BigEndianU32::from_bytes(property.value)
  183. .expect("not enough bytes for #size-cells value")
  184. .get() as usize;
  185. }
  186. _ => {}
  187. }
  188. }
  189. cell_sizes
  190. }
  191. /// Searches for the interrupt parent, if the node contains one
  192. pub fn interrupt_parent(self) -> Option<FdtNode<'b, 'a>> {
  193. self.properties()
  194. .find(|p| p.name == "interrupt-parent")
  195. .and_then(|p| self.header.find_phandle(BigEndianU32::from_bytes(p.value)?.get()))
  196. }
  197. /// `#interrupt-cells` property
  198. pub fn interrupt_cells(self) -> Option<usize> {
  199. let mut interrupt_cells = None;
  200. if let Some(prop) = self.properties().find(|p| p.name == "#interrupt-cells") {
  201. interrupt_cells = BigEndianU32::from_bytes(prop.value).map(|n| n.get() as usize)
  202. }
  203. interrupt_cells
  204. }
  205. /// `interrupts` property
  206. pub fn interrupts(self) -> Option<impl Iterator<Item = usize> + 'a> {
  207. let sizes = self.interrupt_cells()?;
  208. let mut interrupt = None;
  209. for prop in self.properties() {
  210. if prop.name == "interrupts" {
  211. let mut stream = FdtData::new(prop.value);
  212. interrupt = Some(core::iter::from_fn(move || {
  213. let interrupt = match sizes {
  214. 1 => stream.u32()?.get() as usize,
  215. 2 => stream.u64()?.get() as usize,
  216. _ => return None,
  217. };
  218. Some(interrupt)
  219. }));
  220. break;
  221. }
  222. }
  223. interrupt
  224. }
  225. pub(crate) fn parent_cell_sizes(self) -> CellSizes {
  226. let mut cell_sizes = CellSizes::default();
  227. if let Some(parent) = self.parent_props {
  228. let parent =
  229. FdtNode { name: "", props: parent, header: self.header, parent_props: None };
  230. cell_sizes = parent.cell_sizes();
  231. }
  232. cell_sizes
  233. }
  234. }
  235. /// The number of cells (big endian u32s) that addresses and sizes take
  236. #[derive(Debug, Clone, Copy)]
  237. pub struct CellSizes {
  238. /// Size of values representing an address
  239. pub address_cells: usize,
  240. /// Size of values representing a size
  241. pub size_cells: usize,
  242. }
  243. impl Default for CellSizes {
  244. fn default() -> Self {
  245. CellSizes { address_cells: 2, size_cells: 1 }
  246. }
  247. }
  248. /// A raw `reg` property value set
  249. #[derive(Debug, Clone, Copy, PartialEq)]
  250. pub struct RawReg<'a> {
  251. /// Big-endian encoded bytes making up the address portion of the property.
  252. /// Length will always be a multiple of 4 bytes.
  253. pub address: &'a [u8],
  254. /// Big-endian encoded bytes making up the size portion of the property.
  255. /// Length will always be a multiple of 4 bytes.
  256. pub size: &'a [u8],
  257. }
  258. pub(crate) fn find_node<'b, 'a: 'b>(
  259. stream: &mut FdtData<'a>,
  260. name: &str,
  261. header: &'b Fdt<'a>,
  262. parent_props: Option<&'a [u8]>,
  263. ) -> Option<FdtNode<'b, 'a>> {
  264. let mut parts = name.splitn(2, '/');
  265. let looking_for = parts.next()?;
  266. stream.skip_nops();
  267. let curr_data = stream.remaining();
  268. match stream.u32()?.get() {
  269. FDT_BEGIN_NODE => {}
  270. _ => return None,
  271. }
  272. let unit_name = CStr::new(stream.remaining()).expect("unit name C str").as_str()?;
  273. let full_name_len = unit_name.len() + 1;
  274. skip_4_aligned(stream, full_name_len);
  275. let looking_contains_addr = looking_for.contains('@');
  276. let addr_name_same = unit_name == looking_for;
  277. let base_name_same = unit_name.split('@').next()? == looking_for;
  278. if (looking_contains_addr && !addr_name_same) || (!looking_contains_addr && !base_name_same) {
  279. *stream = FdtData::new(curr_data);
  280. skip_current_node(stream, header);
  281. return None;
  282. }
  283. let next_part = match parts.next() {
  284. None | Some("") => {
  285. return Some(FdtNode::new(unit_name, header, stream.remaining(), parent_props))
  286. }
  287. Some(part) => part,
  288. };
  289. stream.skip_nops();
  290. let parent_props = Some(stream.remaining());
  291. while stream.peek_u32()?.get() == FDT_PROP {
  292. let _ = NodeProperty::parse(stream, header);
  293. }
  294. while stream.peek_u32()?.get() == FDT_BEGIN_NODE {
  295. if let Some(p) = find_node(stream, next_part, header, parent_props) {
  296. return Some(p);
  297. }
  298. }
  299. stream.skip_nops();
  300. if stream.u32()?.get() != FDT_END_NODE {
  301. return None;
  302. }
  303. None
  304. }
  305. // FIXME: this probably needs refactored
  306. pub(crate) fn all_nodes<'b, 'a: 'b>(header: &'b Fdt<'a>) -> impl Iterator<Item = FdtNode<'b, 'a>> {
  307. let mut stream = FdtData::new(header.structs_block());
  308. let mut done = false;
  309. let mut parents: [&[u8]; 64] = [&[]; 64];
  310. let mut parent_index = 0;
  311. core::iter::from_fn(move || {
  312. if stream.is_empty() || done {
  313. return None;
  314. }
  315. while stream.peek_u32()?.get() == FDT_END_NODE {
  316. parent_index -= 1;
  317. stream.skip(4);
  318. }
  319. if stream.peek_u32()?.get() == FDT_END {
  320. done = true;
  321. return None;
  322. }
  323. while stream.peek_u32()?.get() == FDT_NOP {
  324. stream.skip(4);
  325. }
  326. match stream.u32()?.get() {
  327. FDT_BEGIN_NODE => {}
  328. _ => return None,
  329. }
  330. let unit_name = CStr::new(stream.remaining()).expect("unit name C str").as_str().unwrap();
  331. let full_name_len = unit_name.len() + 1;
  332. skip_4_aligned(&mut stream, full_name_len);
  333. let curr_node = stream.remaining();
  334. parent_index += 1;
  335. parents[parent_index] = curr_node;
  336. while stream.peek_u32()?.get() == FDT_NOP {
  337. stream.skip(4);
  338. }
  339. while stream.peek_u32()?.get() == FDT_PROP {
  340. NodeProperty::parse(&mut stream, header);
  341. }
  342. Some(FdtNode {
  343. name: if unit_name.is_empty() { "/" } else { unit_name },
  344. header,
  345. parent_props: match parent_index {
  346. 1 => None,
  347. _ => Some(parents[parent_index - 1]),
  348. },
  349. props: curr_node,
  350. })
  351. })
  352. }
  353. pub(crate) fn skip_current_node<'a>(stream: &mut FdtData<'a>, header: &Fdt<'a>) {
  354. assert_eq!(stream.u32().unwrap().get(), FDT_BEGIN_NODE, "bad node");
  355. let unit_name = CStr::new(stream.remaining()).expect("unit_name C str").as_str().unwrap();
  356. let full_name_len = unit_name.len() + 1;
  357. skip_4_aligned(stream, full_name_len);
  358. while stream.peek_u32().unwrap().get() == FDT_PROP {
  359. NodeProperty::parse(stream, header);
  360. }
  361. while stream.peek_u32().unwrap().get() == FDT_BEGIN_NODE {
  362. skip_current_node(stream, header);
  363. }
  364. stream.skip_nops();
  365. assert_eq!(stream.u32().unwrap().get(), FDT_END_NODE, "bad node");
  366. }
  367. /// A node property
  368. #[derive(Debug, Clone, Copy)]
  369. pub struct NodeProperty<'a> {
  370. /// Property name
  371. pub name: &'a str,
  372. /// Property value
  373. pub value: &'a [u8],
  374. }
  375. impl<'a> NodeProperty<'a> {
  376. /// Attempt to parse the property value as a `usize`
  377. pub fn as_usize(self) -> Option<usize> {
  378. match self.value.len() {
  379. 4 => BigEndianU32::from_bytes(self.value).map(|i| i.get() as usize),
  380. 8 => BigEndianU64::from_bytes(self.value).map(|i| i.get() as usize),
  381. _ => None,
  382. }
  383. }
  384. /// Attempt to parse the property value as a `&str`
  385. pub fn as_str(self) -> Option<&'a str> {
  386. core::str::from_utf8(self.value).ok()
  387. }
  388. fn parse(stream: &mut FdtData<'a>, header: &Fdt<'a>) -> Self {
  389. match stream.u32().unwrap().get() {
  390. FDT_PROP => {}
  391. other => panic!("bad prop, tag: {}", other),
  392. }
  393. let prop = FdtProperty::from_bytes(stream).expect("FDT property");
  394. let data_len = prop.len.get() as usize;
  395. let data = &stream.remaining()[..data_len];
  396. skip_4_aligned(stream, data_len);
  397. NodeProperty { name: header.str_at_offset(prop.name_offset.get() as usize), value: data }
  398. }
  399. }
  400. /// A memory reservation
  401. #[derive(Debug)]
  402. #[repr(C)]
  403. pub struct MemoryReservation {
  404. pub(crate) address: BigEndianU64,
  405. pub(crate) size: BigEndianU64,
  406. }
  407. impl MemoryReservation {
  408. /// Pointer representing the memory reservation address
  409. pub fn address(&self) -> *const u8 {
  410. self.address.get() as usize as *const u8
  411. }
  412. /// Size of the memory reservation
  413. pub fn size(&self) -> usize {
  414. self.size.get() as usize
  415. }
  416. pub(crate) fn from_bytes(bytes: &mut FdtData<'_>) -> Option<Self> {
  417. let address = bytes.u64()?;
  418. let size = bytes.u64()?;
  419. Some(Self { address, size })
  420. }
  421. }
  422. fn skip_4_aligned(stream: &mut FdtData<'_>, len: usize) {
  423. stream.skip((len + 3) & !0x3);
  424. }