pvmfw: Allow non-assignable device nodes to be labeled

Assignable devices list is provided by the XML, so validating whether
the labeled nodes is valid device node is too much check and only makes
writing DT hard.

This CL relax the condition by not returning error for labeled nodes
that aren't backed by physical device nodes.

Bug: 323453334
Test: Manually with markdown preview \
  atest libpvmfw.device_assignment.test
Change-Id: I98e0173f9536d52c1fd8eb40075c67c2361ce52c
diff --git a/docs/device_assignment.md b/docs/device_assignment.md
index 4c5b477..1166cdf 100644
--- a/docs/device_assignment.md
+++ b/docs/device_assignment.md
@@ -165,10 +165,10 @@
 ```
 
 If you compile the above with `dtc -@`, then you'll get `__symbols__` for free.
-The generated `__symbols__` indicates that there are four assignable devices.
+`__symbol__` has label of nodes, and it's required for the next step.
 
 ```dts
-    // generated __symbols__. AVF will ignore non-overlayable nodes.
+    // generated __symbols__
     __symbols__ {
         iommu0 = "/host/iommu0";
         iommu1 = "/host/iommu1";
@@ -200,10 +200,10 @@
 
 * `<kind>`: Device kind. Currently only used for debugging purposes and not used
   for device assignment.
-* `<dtbo_label>`: Label in the VM DTBO (i.e. symbols in `__symbols__`). Must be
-  unique.
+* `<dtbo_label>`: Label in the VM DTBO (i.e. symbol in `__symbols__`). Must be
+  non-empty and unique in the XML.
 * `<sysfs_path>`: Sysfs path of the device in host, used to bind to the VFIO
-  driver. Must be unique in the XML.
+  driver. Must be non-empty and unique in the XML.
 
 ## Boot with VM DTBO
 
diff --git a/pvmfw/src/device_assignment.rs b/pvmfw/src/device_assignment.rs
index b8912ce..d4f87c6 100644
--- a/pvmfw/src/device_assignment.rs
+++ b/pvmfw/src/device_assignment.rs
@@ -167,9 +167,7 @@
     //           rng { ... };      // Actual device node is here. If overlaid, path would be "/rng"
     //         };
     //       };
-    //       __symbols__ {         // List of assignable devices
-    //         // Each property describes an assigned device device information.
-    //         // property name is the device label, and property value is the path in the VM DTBO.
+    //       __symbols__ {         // Contains list of assignable devices
     //         rng = "/fragment@rng/__overlay__/rng";
     //       };
     //    };
@@ -581,10 +579,13 @@
 
         let Some(node) = fdt.node(&node_path)? else { return Ok(None) };
 
-        // Note: Currently can only assign devices backed by physical devices.
+        // Currently can only assign devices backed by physical devices.
         let phandle = dtbo_node.get_phandle()?.ok_or(DeviceAssignmentError::InvalidDtbo)?;
-        let physical_device =
-            physical_devices.get(&phandle).ok_or(DeviceAssignmentError::InvalidDtbo)?;
+        let Some(physical_device) = physical_devices.get(&phandle) else {
+            // If labeled DT node isn't backed by physical device node, then just return None.
+            // It's not an error because such node can be a dependency of assignable device nodes.
+            return Ok(None);
+        };
 
         let reg = parse_node_reg(&node)?;
         Self::validate_reg(&reg, &physical_device.reg, hypervisor)?;