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