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()
diff --git a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
index 691d15a..91693f7 100644
--- a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
+++ b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
@@ -1,61 +1,118 @@
 /dts-v1/;
-/plugin/;
 
 / {
-	fragment@rng {
-		target-path = "/";
-		__overlay__ {
-			rng {
-				compatible = "android,rng";
-				android,rng,ignore-gctrl-reset;
-				android,pvmfw,phy-reg = <0x0 0x12F00000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x12E40000>;
-				android,pvmfw,phy-sid = <3>;
-			};
-		};
-	};
-
-	fragment@sensor {
-		target-path = "/";
-		__overlay__ {
-			light {
-				compatible = "android,light";
-				version = <0x1 0x2>;
-				android,pvmfw,phy-reg = <0x0 0xF00000 0x1000>, <0x0 0xF10000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x40000>, <0x0 0x50000>;
-				android,pvmfw,phy-sid = <4>, <5>;
-			};
-		};
-	};
-
-	fragment@led {
-		target-path = "/";
-		__overlay__ {
-			led {
-				compatible = "android,led";
-				prop = <0x555>;
-				android,pvmfw,phy-reg = <0x0 0x12000000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x12E40000>;
-				android,pvmfw,phy-sid = <3>;
-			};
-		};
-	};
-
-	fragment@backlight {
-		target-path = "/";
-		__overlay__ {
-			backlight {
-				compatible = "android,backlight";
-				android,backlight,ignore-gctrl-reset;
-				android,pvmfw,phy-reg = <0x0 0x300 0x100>;
-			};
-		};
-	};
-
-	__symbols__ {
-		rng = "/fragment@rng/__overlay__/rng";
-		sensor = "/fragment@sensor/__overlay__/light";
-		led = "/fragment@led/__overlay__/led";
-		backlight = "/fragment@backlight/__overlay__/backlight";
-	};
+    host {
+        #address-cells = <0x2>;
+        #size-cells = <0x1>;
+        rng {
+            reg = <0x0 0x12f00000 0x1000>;
+            iommus = <0x1 0x3>;
+            android,pvmfw,target = <0x2>;
+        };
+        light {
+            reg = <0x0 0x00f00000 0x1000>, <0x0 0x00f10000 0x1000>;
+            iommus = <0x3 0x4>, <0x4 0x5>;
+            android,pvmfw,target = <0x5>;
+        };
+        led {
+            reg = <0x0 0x12000000 0x1000>;
+            iommus = <0x1 0x3>;
+            android,pvmfw,target = <0x6>;
+        };
+        bus0 {
+            #address-cells = <0x1>;
+            #size-cells = <0x1>;
+            backlight {
+                reg = <0x300 0x100>;
+                android,pvmfw,target = <0x7>;
+            };
+        };
+        iommu0 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x12e40000>;
+            phandle = <0x1>;
+        };
+        iommu1 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x40000>;
+            phandle = <0x3>;
+        };
+        iommu2 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x50000>;
+            phandle = <0x4>;
+        };
+    };
+    fragment@rng {
+        target-path = "/";
+        __overlay__ {
+            rng {
+                compatible = "android,rng";
+                android,rng,ignore-gctrl-reset;
+                phandle = <0x2>;
+            };
+        };
+    };
+    fragment@sensor {
+        target-path = "/";
+        __overlay__ {
+            light {
+                compatible = "android,light";
+                version = <0x1 0x2>;
+                phandle = <0x5>;
+            };
+        };
+    };
+    fragment@led {
+        target-path = "/";
+        __overlay__ {
+            led {
+                compatible = "android,led";
+                prop = <0x555>;
+                phandle = <0x6>;
+            };
+        };
+    };
+    fragment@backlight {
+        target-path = "/";
+        __overlay__ {
+            bus0 {
+                backlight {
+                    compatible = "android,backlight";
+                    android,backlight,ignore-gctrl-reset;
+                    phandle = <0x7>;
+                };
+            };
+        };
+    };
+    __symbols__ {
+        iommu0 = "/host/iommu0";
+        iommu1 = "/host/iommu1";
+        iommu2 = "/host/iommu2";
+        rng = "/fragment@rng/__overlay__/rng";
+        light = "/fragment@sensor/__overlay__/light";
+        led = "/fragment@led/__overlay__/led";
+        backlight = "/fragment@backlight/__overlay__/bus0/backlight";
+    };
+    __local_fixups__ {
+        host {
+            rng {
+                iommus = <0x0>;
+                android,pvmfw,target = <0x0>;
+            };
+            light {
+                iommus = <0x0 0x8>;
+                android,pvmfw,target = <0x0>;
+            };
+            led {
+                iommus = <0x0>;
+                android,pvmfw,target = <0x0>;
+            };
+            bus0 {
+                backlight {
+                    android,pvmfw,target = <0x0>;
+                };
+            };
+        };
+    };
 };
diff --git a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_without_symbols.dts b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_without_symbols.dts
index 18b9e79..2bc8081 100644
--- a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_without_symbols.dts
+++ b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_without_symbols.dts
@@ -1,43 +1,114 @@
 /dts-v1/;
-/plugin/;
 
 / {
-	fragment@rng {
-		target-path = "/";
-		__overlay__ {
-			rng {
-				compatible = "android,rng";
-				android,rng,ignore-gctrl-reset;
-				android,pvmfw,phy-reg = <0x0 0x12F00000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x12E40000>;
-				android,pvmfw,phy-sid = <3>;
-			};
-		};
-	};
-
-	fragment@sensor {
-		target-path = "/";
-		__overlay__ {
-			light {
-				compatible = "android,light";
-				version = <0x1 0x2>;
-				android,pvmfw,phy-reg = <0x0 0xF00000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x40000>, <0x0 0x50000>;
-				android,pvmfw,phy-sid = <4>, <5>;
-			};
-		};
-	};
-
-	fragment@led {
-		target-path = "/";
-		__overlay__ {
-			led {
-				compatible = "android,led";
-				prop;
-				android,pvmfw,phy-reg = <0x0 0x12F00000 0x1000>;
-				android,pvmfw,phy-iommu = <0x0 0x20000>, <0x0 0x30000>;
-				android,pvmfw,phy-sid = <7>, <8>;
-			};
-		};
-	};
+    host {
+        #address-cells = <0x2>;
+        #size-cells = <0x1>;
+        rng {
+            reg = <0x0 0x12f00000 0x1000>;
+            iommus = <0x1 0x3>;
+            android,pvmfw,target = <0x2>;
+        };
+        light {
+            reg = <0x0 0x00f00000 0x1000>, <0x0 0x00f10000 0x1000>;
+            iommus = <0x3 0x4>, <0x4 0x5>;
+            android,pvmfw,target = <0x5>;
+        };
+        led {
+            reg = <0x0 0x12000000 0x1000>;
+            iommus = <0x1 0x3>;
+            android,pvmfw,target = <0x6>;
+        };
+        bus0 {
+            #address-cells = <0x1>;
+            #size-cells = <0x1>;
+            backlight {
+                reg = <0x300 0x100>;
+                android,pvmfw,target = <0x7>;
+            };
+        };
+        iommu0 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x12e40000>;
+            phandle = <0x1>;
+        };
+        iommu1 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x40000>;
+            phandle = <0x3>;
+        };
+        iommu2 {
+            #iommu-cells = <0x1>;
+            android,pvmfw,token = <0x0 0x50000>;
+            phandle = <0x4>;
+        };
+    };
+    fragment@rng {
+        target-path = "/";
+        __overlay__ {
+            rng {
+                compatible = "android,rng";
+                android,rng,ignore-gctrl-reset;
+                phandle = <0x2>;
+            };
+        };
+    };
+    fragment@sensor {
+        target-path = "/";
+        __overlay__ {
+            light {
+                compatible = "android,light";
+                version = <0x1 0x2>;
+                phandle = <0x5>;
+            };
+        };
+    };
+    fragment@led {
+        target-path = "/";
+        __overlay__ {
+            led {
+                compatible = "android,led";
+                prop = <0x555>;
+                phandle = <0x6>;
+            };
+        };
+    };
+    fragment@backlight {
+        target-path = "/";
+        __overlay__ {
+            bus0 {
+                backlight {
+                    compatible = "android,backlight";
+                    android,backlight,ignore-gctrl-reset;
+                    phandle = <0x7>;
+                };
+            };
+        };
+    };
+    __symbols__ {
+        iommu0 = "/host/iommu0";
+        iommu1 = "/host/iommu1";
+        iommu2 = "/host/iommu2";
+    };
+    __local_fixups__ {
+        host {
+            rng {
+                iommus = <0x0>;
+                android,pvmfw,target = <0x0>;
+            };
+            light {
+                iommus = <0x0 0x8>;
+                android,pvmfw,target = <0x0>;
+            };
+            led {
+                iommus = <0x0>;
+                android,pvmfw,target = <0x0>;
+            };
+            bus0 {
+                backlight {
+                    android,pvmfw,target = <0x0>;
+                };
+            };
+        };
+    };
 };
diff --git a/pvmfw/testdata/test_pvmfw_devices_without_iommus.dts b/pvmfw/testdata/test_pvmfw_devices_without_iommus.dts
index 2036c9c..1a12c87 100644
--- a/pvmfw/testdata/test_pvmfw_devices_without_iommus.dts
+++ b/pvmfw/testdata/test_pvmfw_devices_without_iommus.dts
@@ -4,11 +4,16 @@
 /include/ "test_crosvm_dt_base.dtsi"
 
 / {
-    backlight@90000000 {
-        compatible = "android,backlight";
-        reg = <0x0 0x9 0x0 0xFF>;
-        interrupts = <0x0 0xF 0x4>;
-        google,eh,ignore-gctrl-reset;
-        status = "okay";
+    bus0 {
+        #address-cells = <0x2>;
+        #size-cells = <0x2>;
+
+        backlight@90000000 {
+            compatible = "android,backlight";
+            reg = <0x0 0x9 0x0 0xFF>;
+            interrupts = <0x0 0xF 0x4>;
+            google,eh,ignore-gctrl-reset;
+            status = "okay";
+        };
     };
 };