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