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