1 // Copyright 2023, 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 //! High-level FDT functions. 16 17 use core::ops::Range; 18 use cstr::cstr; 19 use libfdt::{self, Fdt, FdtError}; 20 21 /// Represents information about a SWIOTLB buffer. 22 #[derive(Debug)] 23 pub struct SwiotlbInfo { 24 /// The address of the SWIOTLB buffer, if available. 25 pub addr: Option<usize>, 26 /// The size of the SWIOTLB buffer. 27 pub size: usize, 28 /// The alignment of the SWIOTLB buffer, if available. 29 pub align: Option<usize>, 30 } 31 32 impl SwiotlbInfo { 33 /// Creates a `SwiotlbInfo` struct from the given device tree. new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo>34 pub fn new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo> { 35 let node = 36 fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next().ok_or(FdtError::NotFound)?; 37 38 let (addr, size, align) = if let Some(mut reg) = node.reg()? { 39 let reg = reg.next().ok_or(FdtError::NotFound)?; 40 let size = reg.size.ok_or(FdtError::NotFound)?; 41 (Some(reg.addr.try_into().unwrap()), size.try_into().unwrap(), None) 42 } else { 43 let size = node.getprop_u64(cstr!("size"))?.ok_or(FdtError::NotFound)?; 44 let align = node.getprop_u64(cstr!("alignment"))?.ok_or(FdtError::NotFound)?; 45 (None, size.try_into().unwrap(), Some(align.try_into().unwrap())) 46 }; 47 Ok(Self { addr, size, align }) 48 } 49 50 /// Returns the fixed range of memory mapped by the SWIOTLB buffer, if available. fixed_range(&self) -> Option<Range<usize>>51 pub fn fixed_range(&self) -> Option<Range<usize>> { 52 self.addr.map(|addr| addr..addr + self.size) 53 } 54 } 55