• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Wrapper around libfdt library. Provides parsing/generating functionality
16 //! to a bare-metal environment.
17 
18 #![no_std]
19 
20 mod iterators;
21 mod libfdt;
22 mod result;
23 mod safe_types;
24 
25 pub use iterators::{
26     AddressRange, CellIterator, CompatibleIterator, DescendantsIterator, MemRegIterator,
27     PropertyIterator, RangesIterator, Reg, RegIterator, SubnodeIterator,
28 };
29 pub use result::{FdtError, Result};
30 pub use safe_types::{FdtHeader, NodeOffset, Phandle, PropOffset, StringOffset};
31 
32 use core::ffi::{c_void, CStr};
33 use core::ops::Range;
34 use libfdt::get_slice_at_ptr;
35 use zerocopy::IntoBytes as _;
36 
37 use crate::libfdt::{Libfdt, LibfdtMut};
38 
39 /// Value of a #address-cells property.
40 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
41 enum AddrCells {
42     Single = 1,
43     Double = 2,
44     Triple = 3,
45 }
46 
47 impl TryFrom<usize> for AddrCells {
48     type Error = FdtError;
49 
try_from(value: usize) -> Result<Self>50     fn try_from(value: usize) -> Result<Self> {
51         match value {
52             x if x == Self::Single as _ => Ok(Self::Single),
53             x if x == Self::Double as _ => Ok(Self::Double),
54             x if x == Self::Triple as _ => Ok(Self::Triple),
55             _ => Err(FdtError::BadNCells),
56         }
57     }
58 }
59 
60 /// Value of a #size-cells property.
61 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
62 enum SizeCells {
63     None = 0,
64     Single = 1,
65     Double = 2,
66 }
67 
68 impl TryFrom<usize> for SizeCells {
69     type Error = FdtError;
70 
try_from(value: usize) -> Result<Self>71     fn try_from(value: usize) -> Result<Self> {
72         match value {
73             x if x == Self::None as _ => Ok(Self::None),
74             x if x == Self::Single as _ => Ok(Self::Single),
75             x if x == Self::Double as _ => Ok(Self::Double),
76             _ => Err(FdtError::BadNCells),
77         }
78     }
79 }
80 
81 /// DT property wrapper to abstract endianess changes
82 #[repr(transparent)]
83 #[derive(Debug)]
84 struct FdtPropertyStruct(libfdt_bindgen::fdt_property);
85 
86 impl AsRef<FdtPropertyStruct> for libfdt_bindgen::fdt_property {
as_ref(&self) -> &FdtPropertyStruct87     fn as_ref(&self) -> &FdtPropertyStruct {
88         let ptr = self as *const _ as *const _;
89         // SAFETY: Types have the same layout (transparent) so the valid reference remains valid.
90         unsafe { &*ptr }
91     }
92 }
93 
94 impl FdtPropertyStruct {
from_offset(fdt: &Fdt, offset: PropOffset) -> Result<&Self>95     fn from_offset(fdt: &Fdt, offset: PropOffset) -> Result<&Self> {
96         Ok(fdt.get_property_by_offset(offset)?.as_ref())
97     }
98 
name_offset(&self) -> StringOffset99     fn name_offset(&self) -> StringOffset {
100         StringOffset(u32::from_be(self.0.nameoff).try_into().unwrap())
101     }
102 
data_len(&self) -> usize103     fn data_len(&self) -> usize {
104         u32::from_be(self.0.len).try_into().unwrap()
105     }
106 
data_ptr(&self) -> *const c_void107     fn data_ptr(&self) -> *const c_void {
108         self.0.data.as_ptr().cast()
109     }
110 }
111 
112 /// DT property.
113 #[derive(Clone, Copy, Debug)]
114 pub struct FdtProperty<'a> {
115     fdt: &'a Fdt,
116     offset: PropOffset,
117     property: &'a FdtPropertyStruct,
118 }
119 
120 impl<'a> FdtProperty<'a> {
new(fdt: &'a Fdt, offset: PropOffset) -> Result<Self>121     fn new(fdt: &'a Fdt, offset: PropOffset) -> Result<Self> {
122         let property = FdtPropertyStruct::from_offset(fdt, offset)?;
123         Ok(Self { fdt, offset, property })
124     }
125 
126     /// Returns the property name
name(&self) -> Result<&'a CStr>127     pub fn name(&self) -> Result<&'a CStr> {
128         self.fdt.string(self.property.name_offset())
129     }
130 
131     /// Returns the property value
value(&self) -> Result<&'a [u8]>132     pub fn value(&self) -> Result<&'a [u8]> {
133         self.fdt.get_from_ptr(self.property.data_ptr(), self.property.data_len())
134     }
135 
next_property(&self) -> Result<Option<Self>>136     fn next_property(&self) -> Result<Option<Self>> {
137         if let Some(offset) = self.fdt.next_property_offset(self.offset)? {
138             Ok(Some(Self::new(self.fdt, offset)?))
139         } else {
140             Ok(None)
141         }
142     }
143 }
144 
145 /// DT node.
146 #[derive(Clone, Copy, Debug)]
147 pub struct FdtNode<'a> {
148     fdt: &'a Fdt,
149     offset: NodeOffset,
150 }
151 
152 impl<'a> FdtNode<'a> {
153     /// Returns parent node.
parent(&self) -> Result<Self>154     pub fn parent(&self) -> Result<Self> {
155         let offset = self.fdt.parent_offset(self.offset)?;
156 
157         Ok(Self { fdt: self.fdt, offset })
158     }
159 
160     /// Returns supernode with depth. Note that root is at depth 0.
supernode_at_depth(&self, depth: usize) -> Result<Self>161     pub fn supernode_at_depth(&self, depth: usize) -> Result<Self> {
162         let offset = self.fdt.supernode_atdepth_offset(self.offset, depth)?;
163 
164         Ok(Self { fdt: self.fdt, offset })
165     }
166 
167     /// Returns the standard (deprecated) device_type <string> property.
device_type(&self) -> Result<Option<&CStr>>168     pub fn device_type(&self) -> Result<Option<&CStr>> {
169         self.getprop_str(c"device_type")
170     }
171 
172     /// Returns the standard reg <prop-encoded-array> property.
reg(&self) -> Result<Option<RegIterator<'a>>>173     pub fn reg(&self) -> Result<Option<RegIterator<'a>>> {
174         if let Some(cells) = self.getprop_cells(c"reg")? {
175             let parent = self.parent()?;
176 
177             let addr_cells = parent.address_cells()?;
178             let size_cells = parent.size_cells()?;
179 
180             Ok(Some(RegIterator::new(cells, addr_cells, size_cells)))
181         } else {
182             Ok(None)
183         }
184     }
185 
186     /// Returns the standard ranges property.
ranges<A, P, S>(&self) -> Result<Option<RangesIterator<'a, A, P, S>>>187     pub fn ranges<A, P, S>(&self) -> Result<Option<RangesIterator<'a, A, P, S>>> {
188         if let Some(cells) = self.getprop_cells(c"ranges")? {
189             let parent = self.parent()?;
190             let addr_cells = self.address_cells()?;
191             let parent_addr_cells = parent.address_cells()?;
192             let size_cells = self.size_cells()?;
193             Ok(Some(RangesIterator::<A, P, S>::new(
194                 cells,
195                 addr_cells,
196                 parent_addr_cells,
197                 size_cells,
198             )))
199         } else {
200             Ok(None)
201         }
202     }
203 
204     /// Returns the node name.
name(&self) -> Result<&'a CStr>205     pub fn name(&self) -> Result<&'a CStr> {
206         let name = self.fdt.get_name(self.offset)?;
207         CStr::from_bytes_with_nul(name).map_err(|_| FdtError::Internal)
208     }
209 
210     /// Returns the value of a given <string> property.
getprop_str(&self, name: &CStr) -> Result<Option<&CStr>>211     pub fn getprop_str(&self, name: &CStr) -> Result<Option<&CStr>> {
212         if let Some(bytes) = self.getprop(name)? {
213             Ok(Some(CStr::from_bytes_with_nul(bytes).map_err(|_| FdtError::BadValue)?))
214         } else {
215             Ok(None)
216         }
217     }
218 
219     /// Returns the value of a given property as an array of cells.
getprop_cells(&self, name: &CStr) -> Result<Option<CellIterator<'a>>>220     pub fn getprop_cells(&self, name: &CStr) -> Result<Option<CellIterator<'a>>> {
221         if let Some(cells) = self.getprop(name)? {
222             Ok(Some(CellIterator::new(cells)))
223         } else {
224             Ok(None)
225         }
226     }
227 
228     /// Returns the value of a given <u32> property.
getprop_u32(&self, name: &CStr) -> Result<Option<u32>>229     pub fn getprop_u32(&self, name: &CStr) -> Result<Option<u32>> {
230         if let Some(bytes) = self.getprop(name)? {
231             Ok(Some(u32::from_be_bytes(bytes.try_into().map_err(|_| FdtError::BadValue)?)))
232         } else {
233             Ok(None)
234         }
235     }
236 
237     /// Returns the value of a given <u64> property.
getprop_u64(&self, name: &CStr) -> Result<Option<u64>>238     pub fn getprop_u64(&self, name: &CStr) -> Result<Option<u64>> {
239         if let Some(bytes) = self.getprop(name)? {
240             Ok(Some(u64::from_be_bytes(bytes.try_into().map_err(|_| FdtError::BadValue)?)))
241         } else {
242             Ok(None)
243         }
244     }
245 
246     /// Returns the value of a given property.
getprop(&self, name: &CStr) -> Result<Option<&'a [u8]>>247     pub fn getprop(&self, name: &CStr) -> Result<Option<&'a [u8]>> {
248         self.fdt.getprop_namelen(self.offset, name.to_bytes())
249     }
250 
251     /// Returns reference to the containing device tree.
fdt(&self) -> &Fdt252     pub fn fdt(&self) -> &Fdt {
253         self.fdt
254     }
255 
256     /// Returns the compatible node of the given name that is next after this node.
next_compatible(self, compatible: &CStr) -> Result<Option<Self>>257     pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
258         let offset = self.fdt.node_offset_by_compatible(self.offset, compatible)?;
259 
260         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
261     }
262 
263     /// Returns the first range of `reg` in this node.
first_reg(&self) -> Result<Reg<u64>>264     pub fn first_reg(&self) -> Result<Reg<u64>> {
265         self.reg()?.ok_or(FdtError::NotFound)?.next().ok_or(FdtError::NotFound)
266     }
267 
address_cells(&self) -> Result<AddrCells>268     fn address_cells(&self) -> Result<AddrCells> {
269         self.fdt.address_cells(self.offset)?.try_into()
270     }
271 
size_cells(&self) -> Result<SizeCells>272     fn size_cells(&self) -> Result<SizeCells> {
273         self.fdt.size_cells(self.offset)?.try_into()
274     }
275 
276     /// Returns an iterator of subnodes
subnodes(&self) -> Result<SubnodeIterator<'a>>277     pub fn subnodes(&self) -> Result<SubnodeIterator<'a>> {
278         SubnodeIterator::new(self)
279     }
280 
first_subnode(&self) -> Result<Option<Self>>281     fn first_subnode(&self) -> Result<Option<Self>> {
282         let offset = self.fdt.first_subnode(self.offset)?;
283 
284         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
285     }
286 
next_subnode(&self) -> Result<Option<Self>>287     fn next_subnode(&self) -> Result<Option<Self>> {
288         let offset = self.fdt.next_subnode(self.offset)?;
289 
290         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
291     }
292 
293     /// Returns an iterator of descendants
descendants(&self) -> DescendantsIterator<'a>294     pub fn descendants(&self) -> DescendantsIterator<'a> {
295         DescendantsIterator::new(self)
296     }
297 
next_node(&self, depth: usize) -> Result<Option<(Self, usize)>>298     fn next_node(&self, depth: usize) -> Result<Option<(Self, usize)>> {
299         if let Some((offset, depth)) = self.fdt.next_node(self.offset, depth)? {
300             Ok(Some((Self { fdt: self.fdt, offset }, depth)))
301         } else {
302             Ok(None)
303         }
304     }
305 
306     /// Returns an iterator of properties
properties(&'a self) -> Result<PropertyIterator<'a>>307     pub fn properties(&'a self) -> Result<PropertyIterator<'a>> {
308         PropertyIterator::new(self)
309     }
310 
first_property(&self) -> Result<Option<FdtProperty<'a>>>311     fn first_property(&self) -> Result<Option<FdtProperty<'a>>> {
312         if let Some(offset) = self.fdt.first_property_offset(self.offset)? {
313             Ok(Some(FdtProperty::new(self.fdt, offset)?))
314         } else {
315             Ok(None)
316         }
317     }
318 
319     /// Returns the phandle
get_phandle(&self) -> Result<Option<Phandle>>320     pub fn get_phandle(&self) -> Result<Option<Phandle>> {
321         // This rewrites the fdt_get_phandle() because it doesn't return error code.
322         if let Some(prop) = self.getprop_u32(c"phandle")? {
323             Ok(Some(prop.try_into()?))
324         } else if let Some(prop) = self.getprop_u32(c"linux,phandle")? {
325             Ok(Some(prop.try_into()?))
326         } else {
327             Ok(None)
328         }
329     }
330 
331     /// Returns the subnode of the given name. The name doesn't need to be nul-terminated.
subnode(&self, name: &CStr) -> Result<Option<Self>>332     pub fn subnode(&self, name: &CStr) -> Result<Option<Self>> {
333         let name = name.to_bytes();
334         let offset = self.fdt.subnode_offset_namelen(self.offset, name)?;
335 
336         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
337     }
338 
339     /// Returns the subnode of the given name bytes
subnode_with_name_bytes(&self, name: &[u8]) -> Result<Option<Self>>340     pub fn subnode_with_name_bytes(&self, name: &[u8]) -> Result<Option<Self>> {
341         let offset = self.fdt.subnode_offset_namelen(self.offset, name)?;
342 
343         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
344     }
345 }
346 
347 impl PartialEq for FdtNode<'_> {
eq(&self, other: &Self) -> bool348     fn eq(&self, other: &Self) -> bool {
349         self.fdt.as_ptr() == other.fdt.as_ptr() && self.offset == other.offset
350     }
351 }
352 
353 /// Mutable FDT node.
354 #[derive(Debug)]
355 pub struct FdtNodeMut<'a> {
356     fdt: &'a mut Fdt,
357     offset: NodeOffset,
358 }
359 
360 impl<'a> FdtNodeMut<'a> {
361     /// Appends a property name-value (possibly empty) pair to the given node.
appendprop<T: AsRef<[u8]>>(&mut self, name: &CStr, value: &T) -> Result<()>362     pub fn appendprop<T: AsRef<[u8]>>(&mut self, name: &CStr, value: &T) -> Result<()> {
363         self.fdt.appendprop(self.offset, name, value.as_ref())
364     }
365 
366     /// Appends a (address, size) pair property to the given node.
appendprop_addrrange(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()>367     pub fn appendprop_addrrange(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()> {
368         let parent = self.parent()?.offset;
369         self.fdt.appendprop_addrrange(parent, self.offset, name, addr, size)
370     }
371 
372     /// Sets a property name-value pair to the given node.
373     ///
374     /// This may create a new prop or replace existing value.
setprop(&mut self, name: &CStr, value: &[u8]) -> Result<()>375     pub fn setprop(&mut self, name: &CStr, value: &[u8]) -> Result<()> {
376         self.fdt.setprop(self.offset, name, value)
377     }
378 
379     /// Sets the value of the given property with the given value, and ensure that the given
380     /// value has the same length as the current value length.
381     ///
382     /// This can only be used to replace existing value.
setprop_inplace(&mut self, name: &CStr, value: &[u8]) -> Result<()>383     pub fn setprop_inplace(&mut self, name: &CStr, value: &[u8]) -> Result<()> {
384         self.fdt.setprop_inplace(self.offset, name, value)
385     }
386 
387     /// Sets the value of the given (address, size) pair property with the given value, and
388     /// ensure that the given value has the same length as the current value length.
389     ///
390     /// This can only be used to replace existing value.
setprop_addrrange_inplace(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()>391     pub fn setprop_addrrange_inplace(&mut self, name: &CStr, addr: u64, size: u64) -> Result<()> {
392         let pair = [addr.to_be(), size.to_be()];
393         self.fdt.setprop_inplace(self.offset, name, pair.as_bytes())
394     }
395 
396     /// Sets a flag-like empty property.
397     ///
398     /// This may create a new prop or replace existing value.
setprop_empty(&mut self, name: &CStr) -> Result<()>399     pub fn setprop_empty(&mut self, name: &CStr) -> Result<()> {
400         self.fdt.setprop(self.offset, name, &[])
401     }
402 
403     /// Deletes the given property.
delprop(&mut self, name: &CStr) -> Result<()>404     pub fn delprop(&mut self, name: &CStr) -> Result<()> {
405         self.fdt.delprop(self.offset, name)
406     }
407 
408     /// Deletes the given property effectively from DT, by setting it with FDT_NOP.
nop_property(&mut self, name: &CStr) -> Result<()>409     pub fn nop_property(&mut self, name: &CStr) -> Result<()> {
410         self.fdt.nop_property(self.offset, name)
411     }
412 
413     /// Trims the size of the given property to new_size.
trimprop(&mut self, name: &CStr, new_size: usize) -> Result<()>414     pub fn trimprop(&mut self, name: &CStr, new_size: usize) -> Result<()> {
415         let prop = self.as_node().getprop(name)?.ok_or(FdtError::NotFound)?;
416 
417         match prop.len() {
418             x if x == new_size => Ok(()),
419             x if x < new_size => Err(FdtError::NoSpace),
420             _ => self.fdt.setprop_placeholder(self.offset, name, new_size).map(|_| ()),
421         }
422     }
423 
424     /// Returns reference to the containing device tree.
fdt(&mut self) -> &mut Fdt425     pub fn fdt(&mut self) -> &mut Fdt {
426         self.fdt
427     }
428 
429     /// Returns immutable FdtNode of this node.
as_node(&self) -> FdtNode430     pub fn as_node(&self) -> FdtNode {
431         FdtNode { fdt: self.fdt, offset: self.offset }
432     }
433 
434     /// Adds new subnodes to the given node.
add_subnodes(self, names: &[&CStr]) -> Result<()>435     pub fn add_subnodes(self, names: &[&CStr]) -> Result<()> {
436         for name in names {
437             self.fdt.add_subnode_namelen(self.offset, name.to_bytes())?;
438         }
439         Ok(())
440     }
441 
442     /// Adds a new subnode to the given node and return it as a FdtNodeMut on success.
add_subnode(self, name: &CStr) -> Result<Self>443     pub fn add_subnode(self, name: &CStr) -> Result<Self> {
444         let name = name.to_bytes();
445         let offset = self.fdt.add_subnode_namelen(self.offset, name)?;
446 
447         Ok(Self { fdt: self.fdt, offset })
448     }
449 
450     /// Adds a new subnode to the given node with name and namelen, and returns it as a FdtNodeMut
451     /// on success.
add_subnode_with_namelen(self, name: &CStr, namelen: usize) -> Result<Self>452     pub fn add_subnode_with_namelen(self, name: &CStr, namelen: usize) -> Result<Self> {
453         let name = &name.to_bytes()[..namelen];
454         let offset = self.fdt.add_subnode_namelen(self.offset, name)?;
455 
456         Ok(Self { fdt: self.fdt, offset })
457     }
458 
459     /// Returns the first subnode of this
first_subnode(self) -> Result<Option<Self>>460     pub fn first_subnode(self) -> Result<Option<Self>> {
461         let offset = self.fdt.first_subnode(self.offset)?;
462 
463         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
464     }
465 
466     /// Returns the next subnode that shares the same parent with this
next_subnode(self) -> Result<Option<Self>>467     pub fn next_subnode(self) -> Result<Option<Self>> {
468         let offset = self.fdt.next_subnode(self.offset)?;
469 
470         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
471     }
472 
473     /// Deletes the current node and returns the next subnode
delete_and_next_subnode(self) -> Result<Option<Self>>474     pub fn delete_and_next_subnode(self) -> Result<Option<Self>> {
475         let next_offset = self.fdt.next_subnode(self.offset)?;
476 
477         self.delete_and_next(next_offset)
478     }
479 
480     /// Returns the next node. Use this API to travel descendant of a node.
481     ///
482     /// Returned depth is relative to the initial node that had called with any of next node APIs.
483     /// Returns None if end of FDT reached or depth becomes negative.
484     ///
485     /// See also: [`next_node_skip_subnodes`], and [`delete_and_next_node`]
next_node(self, depth: usize) -> Result<Option<(Self, usize)>>486     pub fn next_node(self, depth: usize) -> Result<Option<(Self, usize)>> {
487         let next = self.fdt.next_node(self.offset, depth)?;
488 
489         Ok(next.map(|(offset, depth)| (Self { fdt: self.fdt, offset }, depth)))
490     }
491 
492     /// Returns the next node skipping subnodes. Use this API to travel descendants of a node while
493     /// ignoring certain node.
494     ///
495     /// Returned depth is relative to the initial node that had called with any of next node APIs.
496     /// Returns None if end of FDT reached or depth becomes negative.
497     ///
498     /// See also: [`next_node`], and [`delete_and_next_node`]
next_node_skip_subnodes(self, depth: usize) -> Result<Option<(Self, usize)>>499     pub fn next_node_skip_subnodes(self, depth: usize) -> Result<Option<(Self, usize)>> {
500         let next = self.fdt.next_node_skip_subnodes(self.offset, depth)?;
501 
502         Ok(next.map(|(offset, depth)| (Self { fdt: self.fdt, offset }, depth)))
503     }
504 
505     /// Deletes this and returns the next node. Use this API to travel descendants of a node while
506     /// removing certain node.
507     ///
508     /// Returned depth is relative to the initial node that had called with any of next node APIs.
509     /// Returns None if end of FDT reached or depth becomes negative.
510     ///
511     /// See also: [`next_node`], and [`next_node_skip_subnodes`]
delete_and_next_node(self, depth: usize) -> Result<Option<(Self, usize)>>512     pub fn delete_and_next_node(self, depth: usize) -> Result<Option<(Self, usize)>> {
513         let next_node = self.fdt.next_node_skip_subnodes(self.offset, depth)?;
514         if let Some((offset, depth)) = next_node {
515             let next_node = self.delete_and_next(Some(offset))?.unwrap();
516             Ok(Some((next_node, depth)))
517         } else {
518             self.delete_and_next(None)?;
519             Ok(None)
520         }
521     }
522 
parent(&'a self) -> Result<FdtNode<'a>>523     fn parent(&'a self) -> Result<FdtNode<'a>> {
524         self.as_node().parent()
525     }
526 
527     /// Returns the compatible node of the given name that is next after this node.
next_compatible(self, compatible: &CStr) -> Result<Option<Self>>528     pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
529         let offset = self.fdt.node_offset_by_compatible(self.offset, compatible)?;
530 
531         Ok(offset.map(|offset| Self { fdt: self.fdt, offset }))
532     }
533 
534     /// Deletes the node effectively by overwriting this node and its subtree with nop tags.
535     /// Returns the next compatible node of the given name.
536     // Side note: without this, filterint out excessive compatible nodes from the DT is impossible.
537     // The reason is that libfdt ensures that the node from where the search for the next
538     // compatible node is started is always a valid one -- except for the special case of offset =
539     // -1 which is to find the first compatible node. So, we can't delete a node and then find the
540     // next compatible node from it.
541     //
542     // We can't do in the opposite direction either. If we call next_compatible to find the next
543     // node, and delete the current node, the Rust borrow checker kicks in. The next node has a
544     // mutable reference to DT, so we can't use current node (which also has a mutable reference to
545     // DT).
delete_and_next_compatible(self, compatible: &CStr) -> Result<Option<Self>>546     pub fn delete_and_next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
547         let next_offset = self.fdt.node_offset_by_compatible(self.offset, compatible)?;
548 
549         self.delete_and_next(next_offset)
550     }
551 
delete_and_next(self, next_offset: Option<NodeOffset>) -> Result<Option<Self>>552     fn delete_and_next(self, next_offset: Option<NodeOffset>) -> Result<Option<Self>> {
553         if Some(self.offset) == next_offset {
554             return Err(FdtError::Internal);
555         }
556 
557         self.fdt.nop_node(self.offset)?;
558 
559         Ok(next_offset.map(|offset| Self { fdt: self.fdt, offset }))
560     }
561 
562     /// Deletes this node effectively from DT, by setting it with FDT_NOP
nop(self) -> Result<()>563     pub fn nop(self) -> Result<()> {
564         self.fdt.nop_node(self.offset)
565     }
566 }
567 
568 /// Wrapper around low-level libfdt functions.
569 #[derive(Debug)]
570 #[repr(transparent)]
571 pub struct Fdt {
572     buffer: [u8],
573 }
574 
575 // SAFETY: Fdt calls check_full() before safely returning a &Self, making it impossible for trait
576 // methods to be called on invalid device trees.
577 unsafe impl Libfdt for Fdt {
as_fdt_slice(&self) -> &[u8]578     fn as_fdt_slice(&self) -> &[u8] {
579         &self.buffer[..self.totalsize()]
580     }
581 }
582 
583 // SAFETY: Fdt calls check_full() before safely returning a &Self, making it impossible for trait
584 // methods to be called on invalid device trees.
585 unsafe impl LibfdtMut for Fdt {
as_fdt_slice_mut(&mut self) -> &mut [u8]586     fn as_fdt_slice_mut(&mut self) -> &mut [u8] {
587         &mut self.buffer
588     }
589 }
590 
591 impl Fdt {
592     /// Wraps a slice containing a Flattened Device Tree.
593     ///
594     /// Fails if the FDT does not pass validation.
from_slice(fdt: &[u8]) -> Result<&Self>595     pub fn from_slice(fdt: &[u8]) -> Result<&Self> {
596         libfdt::check_full(fdt)?;
597         // SAFETY: The FDT was validated.
598         let fdt = unsafe { Self::unchecked_from_slice(fdt) };
599 
600         Ok(fdt)
601     }
602 
603     /// Wraps a mutable slice containing a Flattened Device Tree.
604     ///
605     /// Fails if the FDT does not pass validation.
from_mut_slice(fdt: &mut [u8]) -> Result<&mut Self>606     pub fn from_mut_slice(fdt: &mut [u8]) -> Result<&mut Self> {
607         libfdt::check_full(fdt)?;
608         // SAFETY: The FDT was validated.
609         let fdt = unsafe { Self::unchecked_from_mut_slice(fdt) };
610 
611         Ok(fdt)
612     }
613 
614     /// Creates an empty Flattened Device Tree with a mutable slice.
create_empty_tree(fdt: &mut [u8]) -> Result<&mut Self>615     pub fn create_empty_tree(fdt: &mut [u8]) -> Result<&mut Self> {
616         libfdt::create_empty_tree(fdt)?;
617 
618         Self::from_mut_slice(fdt)
619     }
620 
621     /// Wraps a slice containing a Flattened Device Tree.
622     ///
623     /// # Safety
624     ///
625     /// It is undefined to call this function on a slice that does not contain a valid device tree.
unchecked_from_slice(fdt: &[u8]) -> &Self626     pub const unsafe fn unchecked_from_slice(fdt: &[u8]) -> &Self {
627         let self_ptr = fdt as *const _ as *const _;
628         // SAFETY: The pointer is non-null, dereferenceable, and points to allocated memory.
629         unsafe { &*self_ptr }
630     }
631 
632     /// Wraps a mutable slice containing a Flattened Device Tree.
633     ///
634     /// # Safety
635     ///
636     /// It is undefined to call this function on a slice that does not contain a valid device tree.
unchecked_from_mut_slice(fdt: &mut [u8]) -> &mut Self637     pub unsafe fn unchecked_from_mut_slice(fdt: &mut [u8]) -> &mut Self {
638         let self_mut_ptr = fdt as *mut _ as *mut _;
639         // SAFETY: The pointer is non-null, dereferenceable, and points to allocated memory.
640         unsafe { &mut *self_mut_ptr }
641     }
642 
643     /// Updates this FDT from another FDT.
clone_from(&mut self, other: &Self) -> Result<()>644     pub fn clone_from(&mut self, other: &Self) -> Result<()> {
645         let new_len = other.buffer.len();
646         if self.buffer.len() < new_len {
647             return Err(FdtError::NoSpace);
648         }
649 
650         let zeroed_len = self.totalsize().checked_sub(new_len);
651         let (cloned, zeroed) = self.buffer.split_at_mut(new_len);
652 
653         cloned.clone_from_slice(&other.buffer);
654         if let Some(len) = zeroed_len {
655             zeroed[..len].fill(0);
656         }
657 
658         Ok(())
659     }
660 
661     /// Unpacks the DT to cover the whole slice it is contained in.
unpack(&mut self) -> Result<()>662     pub fn unpack(&mut self) -> Result<()> {
663         self.open_into_self()
664     }
665 
666     /// Packs the DT to take a minimum amount of memory.
667     ///
668     /// Doesn't shrink the underlying memory slice.
pack(&mut self) -> Result<()>669     pub fn pack(&mut self) -> Result<()> {
670         LibfdtMut::pack(self)
671     }
672 
673     /// Applies a DT overlay on the base DT.
674     ///
675     /// # Safety
676     ///
677     /// As libfdt corrupts the input DT on failure, `self` should be discarded on error:
678     ///
679     ///     let fdt = fdt.apply_overlay(overlay)?;
680     ///
681     /// Furthermore, `overlay` is _always_ corrupted by libfdt and will never refer to a valid
682     /// `Fdt` after this function returns and must therefore be discarded by the caller.
apply_overlay<'a>(&'a mut self, overlay: &mut Fdt) -> Result<&'a mut Self>683     pub unsafe fn apply_overlay<'a>(&'a mut self, overlay: &mut Fdt) -> Result<&'a mut Self> {
684         // SAFETY: Our caller will properly discard overlay and/or self as needed.
685         unsafe { self.overlay_apply(overlay) }?;
686 
687         Ok(self)
688     }
689 
690     /// Returns an iterator of memory banks specified the "/memory" node.
691     /// Throws an error when the "/memory" is not found in the device tree.
692     ///
693     /// NOTE: This does not support individual "/memory@XXXX" banks.
memory(&self) -> Result<MemRegIterator>694     pub fn memory(&self) -> Result<MemRegIterator> {
695         let node = self.root().subnode(c"memory")?.ok_or(FdtError::NotFound)?;
696         if node.device_type()? != Some(c"memory") {
697             return Err(FdtError::BadValue);
698         }
699         node.reg()?.ok_or(FdtError::BadValue).map(MemRegIterator::new)
700     }
701 
702     /// Returns the first memory range in the `/memory` node.
first_memory_range(&self) -> Result<Range<usize>>703     pub fn first_memory_range(&self) -> Result<Range<usize>> {
704         self.memory()?.next().ok_or(FdtError::NotFound)
705     }
706 
707     /// Returns the standard /chosen node.
chosen(&self) -> Result<Option<FdtNode>>708     pub fn chosen(&self) -> Result<Option<FdtNode>> {
709         self.root().subnode(c"chosen")
710     }
711 
712     /// Returns the standard /chosen node as mutable.
chosen_mut(&mut self) -> Result<Option<FdtNodeMut>>713     pub fn chosen_mut(&mut self) -> Result<Option<FdtNodeMut>> {
714         self.node_mut(c"/chosen")
715     }
716 
717     /// Returns the root node of the tree.
root(&self) -> FdtNode718     pub fn root(&self) -> FdtNode {
719         FdtNode { fdt: self, offset: NodeOffset::ROOT }
720     }
721 
722     /// Returns the standard /__symbols__ node.
symbols(&self) -> Result<Option<FdtNode>>723     pub fn symbols(&self) -> Result<Option<FdtNode>> {
724         self.root().subnode(c"__symbols__")
725     }
726 
727     /// Returns the standard /__symbols__ node as mutable
symbols_mut(&mut self) -> Result<Option<FdtNodeMut>>728     pub fn symbols_mut(&mut self) -> Result<Option<FdtNodeMut>> {
729         self.node_mut(c"/__symbols__")
730     }
731 
732     /// Returns a tree node by its full path.
node(&self, path: &CStr) -> Result<Option<FdtNode>>733     pub fn node(&self, path: &CStr) -> Result<Option<FdtNode>> {
734         let offset = self.path_offset_namelen(path.to_bytes())?;
735 
736         Ok(offset.map(|offset| FdtNode { fdt: self, offset }))
737     }
738 
739     /// Iterate over nodes with a given compatible string.
compatible_nodes<'a>(&'a self, compatible: &'a CStr) -> Result<CompatibleIterator<'a>>740     pub fn compatible_nodes<'a>(&'a self, compatible: &'a CStr) -> Result<CompatibleIterator<'a>> {
741         CompatibleIterator::new(self, compatible)
742     }
743 
744     /// Returns max phandle in the tree.
max_phandle(&self) -> Result<Phandle>745     pub fn max_phandle(&self) -> Result<Phandle> {
746         self.find_max_phandle()
747     }
748 
749     /// Returns a node with the phandle
node_with_phandle(&self, phandle: Phandle) -> Result<Option<FdtNode>>750     pub fn node_with_phandle(&self, phandle: Phandle) -> Result<Option<FdtNode>> {
751         let offset = self.node_offset_by_phandle(phandle)?;
752 
753         Ok(offset.map(|offset| FdtNode { fdt: self, offset }))
754     }
755 
756     /// Returns a mutable node with the phandle
node_mut_with_phandle(&mut self, phandle: Phandle) -> Result<Option<FdtNodeMut>>757     pub fn node_mut_with_phandle(&mut self, phandle: Phandle) -> Result<Option<FdtNodeMut>> {
758         let offset = self.node_offset_by_phandle(phandle)?;
759 
760         Ok(offset.map(|offset| FdtNodeMut { fdt: self, offset }))
761     }
762 
763     /// Returns the mutable root node of the tree.
root_mut(&mut self) -> FdtNodeMut764     pub fn root_mut(&mut self) -> FdtNodeMut {
765         FdtNodeMut { fdt: self, offset: NodeOffset::ROOT }
766     }
767 
768     /// Returns a mutable tree node by its full path.
node_mut(&mut self, path: &CStr) -> Result<Option<FdtNodeMut>>769     pub fn node_mut(&mut self, path: &CStr) -> Result<Option<FdtNodeMut>> {
770         let offset = self.path_offset_namelen(path.to_bytes())?;
771 
772         Ok(offset.map(|offset| FdtNodeMut { fdt: self, offset }))
773     }
774 
next_node_skip_subnodes( &self, node: NodeOffset, depth: usize, ) -> Result<Option<(NodeOffset, usize)>>775     fn next_node_skip_subnodes(
776         &self,
777         node: NodeOffset,
778         depth: usize,
779     ) -> Result<Option<(NodeOffset, usize)>> {
780         let mut iter = self.next_node(node, depth)?;
781         while let Some((offset, next_depth)) = iter {
782             if next_depth <= depth {
783                 return Ok(Some((offset, next_depth)));
784             }
785             iter = self.next_node(offset, next_depth)?;
786         }
787 
788         Ok(None)
789     }
790 
791     /// Returns the device tree as a slice (may be smaller than the containing buffer).
as_slice(&self) -> &[u8]792     pub fn as_slice(&self) -> &[u8] {
793         self.as_fdt_slice()
794     }
795 
get_from_ptr(&self, ptr: *const c_void, len: usize) -> Result<&[u8]>796     fn get_from_ptr(&self, ptr: *const c_void, len: usize) -> Result<&[u8]> {
797         get_slice_at_ptr(self.as_fdt_slice(), ptr.cast(), len).ok_or(FdtError::Internal)
798     }
799 
800     /// Returns a shared pointer to the device tree.
as_ptr(&self) -> *const c_void801     pub fn as_ptr(&self) -> *const c_void {
802         self.buffer.as_ptr().cast()
803     }
804 
header(&self) -> &FdtHeader805     fn header(&self) -> &FdtHeader {
806         let p = self.as_ptr().cast::<libfdt_bindgen::fdt_header>();
807         // SAFETY: A valid FDT (verified by constructor) must contain a valid fdt_header.
808         let header = unsafe { &*p };
809         header.as_ref()
810     }
811 
totalsize(&self) -> usize812     fn totalsize(&self) -> usize {
813         self.header().totalsize.get().try_into().unwrap()
814     }
815 }
816