node.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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, MemoryRange},
  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. pub fn ranges(self) -> Option<impl Iterator<Item = crate::MemoryRange> + 'a> {
  147. let sizes = self.parent_cell_sizes();
  148. if sizes.address_cells > 2 || sizes.size_cells > 2 {
  149. return None;
  150. }
  151. let mut ranges = None;
  152. for prop in self.properties() {
  153. if prop.name == "ranges" {
  154. let mut stream = FdtData::new(prop.value);
  155. ranges = Some(core::iter::from_fn(move || {
  156. let child_bus_address = match sizes.address_cells {
  157. 1 => stream.u32()?.get() as usize,
  158. 2 => stream.u64()?.get() as usize,
  159. _ => return None,
  160. };
  161. let parent_bus_address = match sizes.address_cells {
  162. 1 => stream.u32()?.get() as usize,
  163. 2 => stream.u64()?.get() as usize,
  164. _ => return None,
  165. };
  166. let size = match sizes.size_cells {
  167. 1 => stream.u32()?.get() as usize,
  168. 2 => stream.u64()?.get() as usize,
  169. _ => return None,
  170. };
  171. Some(MemoryRange { child_bus_address, parent_bus_address, size })
  172. }));
  173. break;
  174. }
  175. }
  176. ranges
  177. }
  178. /// Convenience method that provides an iterator over the raw bytes for the
  179. /// address and size values inside of the `reg` property
  180. pub fn raw_reg(self) -> Option<impl Iterator<Item = RawReg<'a>> + 'a> {
  181. let sizes = self.parent_cell_sizes();
  182. if let Some(prop) = self.property("reg") {
  183. let mut stream = FdtData::new(prop.value);
  184. return Some(core::iter::from_fn(move || {
  185. Some(RawReg {
  186. address: stream.take(sizes.address_cells * 4)?,
  187. size: stream.take(sizes.size_cells * 4)?,
  188. })
  189. }));
  190. }
  191. None
  192. }
  193. /// `compatible` property
  194. pub fn compatible(self) -> Option<Compatible<'a>> {
  195. let mut s = None;
  196. for prop in self.properties() {
  197. if prop.name == "compatible" {
  198. s = Some(Compatible { data: prop.value });
  199. }
  200. }
  201. s
  202. }
  203. /// Cell sizes for child nodes
  204. pub fn cell_sizes(self) -> CellSizes {
  205. let mut cell_sizes = CellSizes::default();
  206. for property in self.properties() {
  207. match property.name {
  208. "#address-cells" => {
  209. cell_sizes.address_cells = BigEndianU32::from_bytes(property.value)
  210. .expect("not enough bytes for #address-cells value")
  211. .get() as usize;
  212. }
  213. "#size-cells" => {
  214. cell_sizes.size_cells = BigEndianU32::from_bytes(property.value)
  215. .expect("not enough bytes for #size-cells value")
  216. .get() as usize;
  217. }
  218. _ => {}
  219. }
  220. }
  221. cell_sizes
  222. }
  223. /// Searches for the interrupt parent, if the node contains one
  224. pub fn interrupt_parent(self) -> Option<FdtNode<'b, 'a>> {
  225. self.properties()
  226. .find(|p| p.name == "interrupt-parent")
  227. .and_then(|p| self.header.find_phandle(BigEndianU32::from_bytes(p.value)?.get()))
  228. }
  229. /// `#interrupt-cells` property
  230. pub fn interrupt_cells(self) -> Option<usize> {
  231. let mut interrupt_cells = None;
  232. if let Some(prop) = self.property("#interrupt-cells") {
  233. interrupt_cells = BigEndianU32::from_bytes(prop.value).map(|n| n.get() as usize)
  234. }
  235. interrupt_cells
  236. }
  237. /// `interrupts` property
  238. pub fn interrupts(self) -> Option<impl Iterator<Item = usize> + 'a> {
  239. let sizes = self.parent_interrupt_cells()?;
  240. let mut interrupt = None;
  241. for prop in self.properties() {
  242. if prop.name == "interrupts" {
  243. let mut stream = FdtData::new(prop.value);
  244. interrupt = Some(core::iter::from_fn(move || {
  245. let interrupt = match sizes {
  246. 1 => stream.u32()?.get() as usize,
  247. 2 => stream.u64()?.get() as usize,
  248. _ => return None,
  249. };
  250. Some(interrupt)
  251. }));
  252. break;
  253. }
  254. }
  255. interrupt
  256. }
  257. pub(crate) fn parent_cell_sizes(self) -> CellSizes {
  258. let mut cell_sizes = CellSizes::default();
  259. if let Some(parent) = self.parent_props {
  260. let parent =
  261. FdtNode { name: "", props: parent, header: self.header, parent_props: None };
  262. cell_sizes = parent.cell_sizes();
  263. }
  264. cell_sizes
  265. }
  266. pub(crate) fn parent_interrupt_cells(self) -> Option<usize> {
  267. let mut interrupt_cells = None;
  268. let parent = self
  269. .property("interrupt-parent")
  270. .and_then(|p| self.header.find_phandle(BigEndianU32::from_bytes(p.value)?.get()))
  271. .or_else(|| {
  272. Some(FdtNode {
  273. name: "",
  274. props: self.parent_props?,
  275. header: self.header,
  276. parent_props: None,
  277. })
  278. });
  279. if let Some(size) = parent.and_then(|parent| parent.interrupt_cells()) {
  280. interrupt_cells = Some(size);
  281. }
  282. interrupt_cells
  283. }
  284. }
  285. /// The number of cells (big endian u32s) that addresses and sizes take
  286. #[derive(Debug, Clone, Copy)]
  287. pub struct CellSizes {
  288. /// Size of values representing an address
  289. pub address_cells: usize,
  290. /// Size of values representing a size
  291. pub size_cells: usize,
  292. }
  293. impl Default for CellSizes {
  294. fn default() -> Self {
  295. CellSizes { address_cells: 2, size_cells: 1 }
  296. }
  297. }
  298. /// A raw `reg` property value set
  299. #[derive(Debug, Clone, Copy, PartialEq)]
  300. pub struct RawReg<'a> {
  301. /// Big-endian encoded bytes making up the address portion of the property.
  302. /// Length will always be a multiple of 4 bytes.
  303. pub address: &'a [u8],
  304. /// Big-endian encoded bytes making up the size portion of the property.
  305. /// Length will always be a multiple of 4 bytes.
  306. pub size: &'a [u8],
  307. }
  308. pub(crate) fn find_node<'b, 'a: 'b>(
  309. stream: &mut FdtData<'a>,
  310. name: &str,
  311. header: &'b Fdt<'a>,
  312. parent_props: Option<&'a [u8]>,
  313. ) -> Option<FdtNode<'b, 'a>> {
  314. let mut parts = name.splitn(2, '/');
  315. let looking_for = parts.next()?;
  316. stream.skip_nops();
  317. let curr_data = stream.remaining();
  318. match stream.u32()?.get() {
  319. FDT_BEGIN_NODE => {}
  320. _ => return None,
  321. }
  322. let unit_name = CStr::new(stream.remaining()).expect("unit name C str").as_str()?;
  323. let full_name_len = unit_name.len() + 1;
  324. skip_4_aligned(stream, full_name_len);
  325. let looking_contains_addr = looking_for.contains('@');
  326. let addr_name_same = unit_name == looking_for;
  327. let base_name_same = unit_name.split('@').next()? == looking_for;
  328. if (looking_contains_addr && !addr_name_same) || (!looking_contains_addr && !base_name_same) {
  329. *stream = FdtData::new(curr_data);
  330. skip_current_node(stream, header);
  331. return None;
  332. }
  333. let next_part = match parts.next() {
  334. None | Some("") => {
  335. return Some(FdtNode::new(unit_name, header, stream.remaining(), parent_props))
  336. }
  337. Some(part) => part,
  338. };
  339. stream.skip_nops();
  340. let parent_props = Some(stream.remaining());
  341. while stream.peek_u32()?.get() == FDT_PROP {
  342. let _ = NodeProperty::parse(stream, header);
  343. }
  344. while stream.peek_u32()?.get() == FDT_BEGIN_NODE {
  345. if let Some(p) = find_node(stream, next_part, header, parent_props) {
  346. return Some(p);
  347. }
  348. }
  349. stream.skip_nops();
  350. if stream.u32()?.get() != FDT_END_NODE {
  351. return None;
  352. }
  353. None
  354. }
  355. // FIXME: this probably needs refactored
  356. pub(crate) fn all_nodes<'b, 'a: 'b>(header: &'b Fdt<'a>) -> impl Iterator<Item = FdtNode<'b, 'a>> {
  357. let mut stream = FdtData::new(header.structs_block());
  358. let mut done = false;
  359. let mut parents: [&[u8]; 64] = [&[]; 64];
  360. let mut parent_index = 0;
  361. core::iter::from_fn(move || {
  362. if stream.is_empty() || done {
  363. return None;
  364. }
  365. while stream.peek_u32()?.get() == FDT_END_NODE {
  366. parent_index -= 1;
  367. stream.skip(4);
  368. }
  369. if stream.peek_u32()?.get() == FDT_END {
  370. done = true;
  371. return None;
  372. }
  373. while stream.peek_u32()?.get() == FDT_NOP {
  374. stream.skip(4);
  375. }
  376. match stream.u32()?.get() {
  377. FDT_BEGIN_NODE => {}
  378. _ => return None,
  379. }
  380. let unit_name = CStr::new(stream.remaining()).expect("unit name C str").as_str().unwrap();
  381. let full_name_len = unit_name.len() + 1;
  382. skip_4_aligned(&mut stream, full_name_len);
  383. let curr_node = stream.remaining();
  384. parent_index += 1;
  385. parents[parent_index] = curr_node;
  386. while stream.peek_u32()?.get() == FDT_NOP {
  387. stream.skip(4);
  388. }
  389. while stream.peek_u32()?.get() == FDT_PROP {
  390. NodeProperty::parse(&mut stream, header);
  391. }
  392. Some(FdtNode {
  393. name: if unit_name.is_empty() { "/" } else { unit_name },
  394. header,
  395. parent_props: match parent_index {
  396. 1 => None,
  397. _ => Some(parents[parent_index - 1]),
  398. },
  399. props: curr_node,
  400. })
  401. })
  402. }
  403. pub(crate) fn skip_current_node<'a>(stream: &mut FdtData<'a>, header: &Fdt<'a>) {
  404. assert_eq!(stream.u32().unwrap().get(), FDT_BEGIN_NODE, "bad node");
  405. let unit_name = CStr::new(stream.remaining()).expect("unit_name C str").as_str().unwrap();
  406. let full_name_len = unit_name.len() + 1;
  407. skip_4_aligned(stream, full_name_len);
  408. while stream.peek_u32().unwrap().get() == FDT_PROP {
  409. NodeProperty::parse(stream, header);
  410. }
  411. while stream.peek_u32().unwrap().get() == FDT_BEGIN_NODE {
  412. skip_current_node(stream, header);
  413. }
  414. stream.skip_nops();
  415. assert_eq!(stream.u32().unwrap().get(), FDT_END_NODE, "bad node");
  416. }
  417. /// A node property
  418. #[derive(Debug, Clone, Copy)]
  419. pub struct NodeProperty<'a> {
  420. /// Property name
  421. pub name: &'a str,
  422. /// Property value
  423. pub value: &'a [u8],
  424. }
  425. impl<'a> NodeProperty<'a> {
  426. /// Attempt to parse the property value as a `usize`
  427. pub fn as_usize(self) -> Option<usize> {
  428. match self.value.len() {
  429. 4 => BigEndianU32::from_bytes(self.value).map(|i| i.get() as usize),
  430. 8 => BigEndianU64::from_bytes(self.value).map(|i| i.get() as usize),
  431. _ => None,
  432. }
  433. }
  434. /// Attempt to parse the property value as a `&str`
  435. pub fn as_str(self) -> Option<&'a str> {
  436. core::str::from_utf8(self.value).map(|s| s.trim_end_matches('\0')).ok()
  437. }
  438. fn parse(stream: &mut FdtData<'a>, header: &Fdt<'a>) -> Self {
  439. match stream.u32().unwrap().get() {
  440. FDT_PROP => {}
  441. other => panic!("bad prop, tag: {}", other),
  442. }
  443. let prop = FdtProperty::from_bytes(stream).expect("FDT property");
  444. let data_len = prop.len.get() as usize;
  445. let data = &stream.remaining()[..data_len];
  446. skip_4_aligned(stream, data_len);
  447. NodeProperty { name: header.str_at_offset(prop.name_offset.get() as usize), value: data }
  448. }
  449. }
  450. /// A memory reservation
  451. #[derive(Debug)]
  452. #[repr(C)]
  453. pub struct MemoryReservation {
  454. pub(crate) address: BigEndianU64,
  455. pub(crate) size: BigEndianU64,
  456. }
  457. impl MemoryReservation {
  458. /// Pointer representing the memory reservation address
  459. pub fn address(&self) -> *const u8 {
  460. self.address.get() as usize as *const u8
  461. }
  462. /// Size of the memory reservation
  463. pub fn size(&self) -> usize {
  464. self.size.get() as usize
  465. }
  466. pub(crate) fn from_bytes(bytes: &mut FdtData<'_>) -> Option<Self> {
  467. let address = bytes.u64()?;
  468. let size = bytes.u64()?;
  469. Some(Self { address, size })
  470. }
  471. }
  472. fn skip_4_aligned(stream: &mut FdtData<'_>, len: usize) {
  473. stream.skip((len + 3) & !0x3);
  474. }