pvmfw: Use new VM DTBO format
Bug: 277993056
Test: atest libpvmfw.device_assignment.test, launch protected VM
Change-Id: Iac3f799f793dab50eacbeac0c0b9339692f149e5
diff --git a/pvmfw/src/device_assignment.rs b/pvmfw/src/device_assignment.rs
index 19ace5f..8d4d840 100644
--- a/pvmfw/src/device_assignment.rs
+++ b/pvmfw/src/device_assignment.rs
@@ -183,6 +183,15 @@
}
}
+fn is_overlayable_node(dtbo_path: &CStr) -> bool {
+ dtbo_path
+ .to_bytes()
+ .split(|char| *char == b'/')
+ .filter(|&component| !component.is_empty())
+ .nth(1)
+ .map_or(false, |name| name == b"__overlay__")
+}
+
impl AsRef<Fdt> for VmDtbo {
fn as_ref(&self) -> &Fdt {
&self.0
@@ -417,6 +426,9 @@
let symbol_prop_value = symbol_prop.value()?;
let dtbo_node_path = CStr::from_bytes_with_nul(symbol_prop_value)
.or(Err(DeviceAssignmentError::InvalidSymbols))?;
+ if !is_overlayable_node(dtbo_node_path) {
+ continue;
+ }
let assigned_device =
AssignedDeviceInfo::parse(fdt, vm_dtbo, dtbo_node_path, &pviommus, hypervisor)?;
if let Some(assigned_device) = assigned_device {
@@ -428,7 +440,15 @@
if assigned_devices.is_empty() {
return Ok(None);
}
+
+ // Clean up any nodes that wouldn't be overlaid but may contain reference to filtered nodes.
+ // Otherwise, `fdt_apply_overlay()` would fail because of missing phandle reference.
filtered_dtbo_paths.push(CString::new("/__symbols__").unwrap());
+ // TODO(b/277993056): Also filter other unused nodes/props in __local_fixups__
+ filtered_dtbo_paths.push(CString::new("/__local_fixups__/host").unwrap());
+
+ // Note: Any node without __overlay__ will be ignored by fdt_apply_overlay,
+ // so doesn't need to be filtered.
Ok(Some(Self { pviommus: unique_pviommus, assigned_devices, filtered_dtbo_paths }))
}
@@ -449,22 +469,6 @@
node.nop()?;
}
- // Filters pvmfw-specific properties in assigned device node.
- const FILTERED_VM_DTBO_PROP: [&CStr; 3] = [
- cstr!("android,pvmfw,phy-reg"),
- cstr!("android,pvmfw,phy-iommu"),
- cstr!("android,pvmfw,phy-sid"),
- ];
- for assigned_device in &self.assigned_devices {
- let mut node = vm_dtbo.node_mut(&assigned_device.dtbo_node_path).unwrap().unwrap();
- for prop in FILTERED_VM_DTBO_PROP {
- match node.nop_property(prop) {
- Err(FdtError::NotFound) => Ok(()), // allows not exists
- other => other,
- }?;
- }
- }
-
Ok(())
}
@@ -649,8 +653,8 @@
let device_info = DeviceAssignmentInfo::parse(fdt, vm_dtbo, &hypervisor).unwrap().unwrap();
let expected = [AssignedDeviceInfo {
- node_path: CString::new("/backlight").unwrap(),
- dtbo_node_path: cstr!("/fragment@backlight/__overlay__/backlight").into(),
+ node_path: CString::new("/bus0/backlight").unwrap(),
+ dtbo_node_path: cstr!("/fragment@backlight/__overlay__/bus0/backlight").into(),
reg: vec![[0x9, 0xFF].into()],
interrupts: into_fdt_prop(vec![0x0, 0xF, 0x4]),
iommus: vec![],
@@ -721,7 +725,8 @@
let led = vm_dtbo.node(cstr!("/fragment@led/__overlay__/led")).unwrap();
assert_eq!(led, None);
- let backlight = vm_dtbo.node(cstr!("/fragment@backlight/__overlay__/backlight")).unwrap();
+ let backlight =
+ vm_dtbo.node(cstr!("/fragment@backlight/__overlay__/bus0/backlight")).unwrap();
assert_eq!(backlight, None);
let symbols_node = vm_dtbo.symbols().unwrap();
@@ -750,6 +755,10 @@
}
device_info.patch(platform_dt).unwrap();
+ let rng_node = platform_dt.node(cstr!("/bus0/backlight")).unwrap().unwrap();
+ let phandle = rng_node.getprop_u32(cstr!("phandle")).unwrap();
+ assert_ne!(None, phandle);
+
// Note: Intentionally not using AssignedDeviceNode for matching all props.
type FdtResult<T> = libfdt::Result<T>;
let expected: Vec<(FdtResult<&CStr>, FdtResult<Vec<u8>>)> = vec![
@@ -757,10 +766,10 @@
(Ok(cstr!("compatible")), Ok(Vec::from(*b"android,backlight\0"))),
(Ok(cstr!("interrupts")), Ok(into_fdt_prop(vec![0x0, 0xF, 0x4]))),
(Ok(cstr!("iommus")), Ok(Vec::new())),
+ (Ok(cstr!("phandle")), Ok(into_fdt_prop(vec![phandle.unwrap()]))),
(Ok(cstr!("reg")), Ok(into_fdt_prop(vec![0x0, 0x9, 0x0, 0xFF]))),
];
- let rng_node = platform_dt.node(cstr!("/backlight")).unwrap().unwrap();
let mut properties: Vec<_> = rng_node
.properties()
.unwrap()