virtualizationservice: Add dtbo to VirtualMachineRawConfig

Bug: 381971307
Test: T/H
Change-Id: Iea377f4e6d2d4c8ae24dc6349c2b0b3ca432e944
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index daa755e..0cde751 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -29,6 +29,7 @@
     ErrorCode::ErrorCode,
 };
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    AssignedDevices::AssignedDevices,
     AssignableDevice::AssignableDevice,
     CpuTopology::CpuTopology,
     DiskImage::DiskImage,
@@ -587,7 +588,19 @@
             check_gdb_allowed(config)?;
         }
 
-        let device_tree_overlay = maybe_create_device_tree_overlay(config, &temporary_directory)?;
+        let mut device_tree_overlays = vec![];
+        if let Some(dt_overlay) = maybe_create_reference_dt_overlay(config, &temporary_directory)? {
+            device_tree_overlays.push(dt_overlay);
+        }
+        if let Some(dtbo) = get_dtbo(config) {
+            let dtbo = File::from(
+                dtbo.as_ref()
+                    .try_clone()
+                    .context("Failed to create VM DTBO from ParcelFileDescriptor")
+                    .or_binder_exception(ExceptionCode::BAD_PARCELABLE)?,
+            );
+            device_tree_overlays.push(dtbo);
+        }
 
         let debug_config = DebugConfig::new(config);
         let ramdump = if !uses_gki_kernel(config) && debug_config.is_ramdump_needed() {
@@ -715,29 +728,30 @@
             }
         };
 
-        let (vfio_devices, dtbo) = if !config.devices.is_empty() {
-            let mut set = HashSet::new();
-            for device in config.devices.iter() {
-                let path = canonicalize(device)
-                    .with_context(|| format!("can't canonicalize {device}"))
-                    .or_service_specific_exception(-1)?;
-                if !set.insert(path) {
-                    return Err(anyhow!("duplicated device {device}"))
-                        .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT);
+        let (vfio_devices, dtbo) = match &config.devices {
+            AssignedDevices::Devices(devices) if !devices.is_empty() => {
+                let mut set = HashSet::new();
+                for device in devices.iter() {
+                    let path = canonicalize(device)
+                        .with_context(|| format!("can't canonicalize {device}"))
+                        .or_service_specific_exception(-1)?;
+                    if !set.insert(path) {
+                        return Err(anyhow!("duplicated device {device}"))
+                            .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT);
+                    }
                 }
+                let devices = GLOBAL_SERVICE.bindDevicesToVfioDriver(devices)?;
+                let dtbo_file = File::from(
+                    GLOBAL_SERVICE
+                        .getDtboFile()?
+                        .as_ref()
+                        .try_clone()
+                        .context("Failed to create VM DTBO from ParcelFileDescriptor")
+                        .or_binder_exception(ExceptionCode::BAD_PARCELABLE)?,
+                );
+                (devices, Some(dtbo_file))
             }
-            let devices = GLOBAL_SERVICE.bindDevicesToVfioDriver(&config.devices)?;
-            let dtbo_file = File::from(
-                GLOBAL_SERVICE
-                    .getDtboFile()?
-                    .as_ref()
-                    .try_clone()
-                    .context("Failed to create VM DTBO from ParcelFileDescriptor")
-                    .or_binder_exception(ExceptionCode::BAD_PARCELABLE)?,
-            );
-            (devices, Some(dtbo_file))
-        } else {
-            (vec![], None)
+            _ => (vec![], None),
         };
         let display_config = if cfg!(paravirtualized_devices) {
             config
@@ -834,7 +848,7 @@
             gdb_port,
             vfio_devices,
             dtbo,
-            device_tree_overlay,
+            device_tree_overlays,
             display_config,
             input_device_options,
             hugepages: config.hugePages,
@@ -931,7 +945,7 @@
     Err(anyhow!("No hashtree digest is extracted from microdroid vendor image"))
 }
 
-fn maybe_create_device_tree_overlay(
+fn maybe_create_reference_dt_overlay(
     config: &VirtualMachineConfig,
     temporary_directory: &Path,
 ) -> binder::Result<Option<File>> {
@@ -1000,6 +1014,16 @@
     Ok(device_tree_overlay)
 }
 
+fn get_dtbo(config: &VirtualMachineConfig) -> Option<&ParcelFileDescriptor> {
+    let VirtualMachineConfig::RawConfig(config) = config else {
+        return None;
+    };
+    match &config.devices {
+        AssignedDevices::Dtbo(dtbo) => dtbo.as_ref(),
+        _ => None,
+    }
+}
+
 fn write_zero_filler(zero_filler_path: &Path) -> Result<()> {
     let file = OpenOptions::new()
         .create_new(true)
@@ -1260,7 +1284,7 @@
             append_kernel_param("androidboot.microdroid.mount_vendor=1", &mut vm_config)
         }
 
-        vm_config.devices.clone_from(&custom_config.devices);
+        vm_config.devices = AssignedDevices::Devices(custom_config.devices.clone());
         vm_config.networkSupported = custom_config.networkSupported;
 
         for param in custom_config.extraKernelCmdlineParams.iter() {
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index affd430..f3b669f 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -125,7 +125,7 @@
     pub gdb_port: Option<NonZeroU16>,
     pub vfio_devices: Vec<VfioDevice>,
     pub dtbo: Option<File>,
-    pub device_tree_overlay: Option<File>,
+    pub device_tree_overlays: Vec<File>,
     pub display_config: Option<DisplayConfig>,
     pub input_device_options: Vec<InputDeviceOption>,
     pub hugepages: bool,
@@ -1157,9 +1157,10 @@
         .context("failed to create control listener")?;
     command.arg("--socket").arg(add_preserved_fd(&mut preserved_fds, control_sock));
 
-    if let Some(dt_overlay) = config.device_tree_overlay {
-        command.arg("--device-tree-overlay").arg(add_preserved_fd(&mut preserved_fds, dt_overlay));
-    }
+    config.device_tree_overlays.into_iter().for_each(|dt_overlay| {
+        let arg = add_preserved_fd(&mut preserved_fds, dt_overlay);
+        command.arg("--device-tree-overlay").arg(arg);
+    });
 
     if cfg!(paravirtualized_devices) {
         if let Some(gpu_config) = &config.gpu_config {