[pvmfw] Separate SWIOTLB info parsing and validation properly
This cl mainly moved the SWIOTLB range check from the SWIOTLB
parsing function to its validation function. This simplifies
the task of moving the SWIOTLB parsing to vmbase for reuse
later.
Bug: 284462758
Test: m pvmfw_img
Change-Id: I42340bc4ad27bb6f2e023b142cdfa4585c9d3627
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index ab851a1..d4c8385 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -438,29 +438,28 @@
}
impl SwiotlbInfo {
+ /// Creates a `SwiotlbInfo` struct from the given device tree.
+ pub fn new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo> {
+ let node =
+ fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next().ok_or(FdtError::NotFound)?;
+
+ let (addr, size, align) = if let Some(mut reg) = node.reg()? {
+ let reg = reg.next().ok_or(FdtError::NotFound)?;
+ let size = reg.size.ok_or(FdtError::NotFound)?;
+ (Some(reg.addr.try_into().unwrap()), size.try_into().unwrap(), None)
+ } else {
+ let size = node.getprop_u64(cstr!("size"))?.ok_or(FdtError::NotFound)?;
+ let align = node.getprop_u64(cstr!("alignment"))?.ok_or(FdtError::NotFound)?;
+ (None, size.try_into().unwrap(), Some(align.try_into().unwrap()))
+ };
+ Ok(Self { addr, size, align })
+ }
+
pub fn fixed_range(&self) -> Option<Range<usize>> {
self.addr.map(|addr| addr..addr + self.size)
}
}
-fn read_swiotlb_info_from(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo> {
- let node =
- fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next().ok_or(FdtError::NotFound)?;
-
- let (addr, size, align) = if let Some(mut reg) = node.reg()? {
- let reg = reg.next().ok_or(FdtError::NotFound)?;
- let size = reg.size.ok_or(FdtError::NotFound)?;
- reg.addr.checked_add(size).ok_or(FdtError::BadValue)?;
- (Some(reg.addr.try_into().unwrap()), size.try_into().unwrap(), None)
- } else {
- let size = node.getprop_u64(cstr!("size"))?.ok_or(FdtError::NotFound)?;
- let align = node.getprop_u64(cstr!("alignment"))?.ok_or(FdtError::NotFound)?;
- (None, size.try_into().unwrap(), Some(align.try_into().unwrap()))
- };
-
- Ok(SwiotlbInfo { addr, size, align })
-}
-
fn validate_swiotlb_info(
swiotlb_info: &SwiotlbInfo,
memory: &Range<usize>,
@@ -478,6 +477,12 @@
return Err(RebootReason::InvalidFdt);
}
+ if let Some(addr) = swiotlb_info.addr {
+ if addr.checked_add(size).is_none() {
+ error!("Invalid swiotlb range: addr:{addr:#x} size:{size:#x}");
+ return Err(RebootReason::InvalidFdt);
+ }
+ }
if let Some(range) = swiotlb_info.fixed_range() {
if !range.is_within(memory) {
error!("swiotlb range {range:#x?} not part of memory range {memory:#x?}");
@@ -636,7 +641,7 @@
RebootReason::InvalidFdt
})?;
- let swiotlb_info = read_swiotlb_info_from(fdt).map_err(|e| {
+ let swiotlb_info = SwiotlbInfo::new_from_fdt(fdt).map_err(|e| {
error!("Failed to read swiotlb info from DT: {e}");
RebootReason::InvalidFdt
})?;