Merge "device_assignment.md: mention how one can list all assignable devices" into main
diff --git a/android/virtmgr/Android.bp b/android/virtmgr/Android.bp
index f0b6881..0148ff6 100644
--- a/android/virtmgr/Android.bp
+++ b/android/virtmgr/Android.bp
@@ -70,6 +70,7 @@
"liblibfdt",
"libfsfdt",
"libhypervisor_props",
+ "libzerocopy",
"libuuid",
// TODO(b/202115393) stabilize the interface
"packagemanager_aidl-rust",
diff --git a/android/virtmgr/src/composite.rs b/android/virtmgr/src/composite.rs
index 681ec59..1219150 100644
--- a/android/virtmgr/src/composite.rs
+++ b/android/virtmgr/src/composite.rs
@@ -15,13 +15,16 @@
//! Functions for creating a composite disk image.
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::Partition::Partition;
-use anyhow::{anyhow, Context, Error};
-use disk::{
- create_composite_disk, create_disk_file, ImagePartitionType, PartitionInfo, MAX_NESTING_DEPTH,
-};
+use anyhow::{bail, Context, Error};
+use disk::{create_composite_disk, ImagePartitionType, PartitionInfo};
use std::fs::{File, OpenOptions};
+use std::io::ErrorKind;
+use std::os::unix::fs::FileExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
+use zerocopy::AsBytes;
+use zerocopy::FromBytes;
+use zerocopy::FromZeroes;
use uuid::Uuid;
@@ -98,7 +101,7 @@
.context("Failed to clone partition image file descriptor")?
.into();
let path = fd_path_for_file(&file);
- let size = get_partition_size(&file, &path)?;
+ let size = get_partition_size(&file)?;
files.push(file);
Ok(PartitionInfo {
@@ -122,16 +125,74 @@
/// Find the size of the partition image in the given file by parsing the header.
///
-/// This will work for raw, QCOW2, composite and Android sparse images.
-fn get_partition_size(partition: &File, path: &Path) -> Result<u64, Error> {
- // TODO: Use `context` once disk::Error implements std::error::Error.
- // TODO: Add check for is_sparse_file
- Ok(create_disk_file(
- partition.try_clone()?,
- /* is_sparse_file */ false,
- MAX_NESTING_DEPTH,
- path,
- )
- .map_err(|e| anyhow!("Failed to open partition image: {}", e))?
- .get_len()?)
+/// This will work for raw and Android sparse images. QCOW2 and composite images aren't supported.
+fn get_partition_size(file: &File) -> Result<u64, Error> {
+ match detect_image_type(file).context("failed to detect partition image type")? {
+ ImageType::Raw => Ok(file.metadata().context("failed to get metadata")?.len()),
+ ImageType::AndroidSparse => {
+ // Source: system/core/libsparse/sparse_format.h
+ #[repr(C)]
+ #[derive(Clone, Copy, Debug, AsBytes, FromZeroes, FromBytes)]
+ struct SparseHeader {
+ magic: u32,
+ major_version: u16,
+ minor_version: u16,
+ file_hdr_sz: u16,
+ chunk_hdr_size: u16,
+ blk_sz: u32,
+ total_blks: u32,
+ total_chunks: u32,
+ image_checksum: u32,
+ }
+ let mut header = SparseHeader::new_zeroed();
+ file.read_exact_at(header.as_bytes_mut(), 0)
+ .context("failed to read android sparse header")?;
+ let len = u64::from(header.total_blks)
+ .checked_mul(header.blk_sz.into())
+ .context("android sparse image len too big")?;
+ Ok(len)
+ }
+ t => bail!("unsupported partition image type: {t:?}"),
+ }
+}
+
+/// Image file types we can detect.
+#[derive(Debug, PartialEq, Eq)]
+enum ImageType {
+ Raw,
+ Qcow2,
+ CompositeDisk,
+ AndroidSparse,
+}
+
+/// Detect image type by looking for magic bytes.
+fn detect_image_type(file: &File) -> std::io::Result<ImageType> {
+ const CDISK_MAGIC: &str = "composite_disk\x1d";
+ const QCOW_MAGIC: u32 = 0x5146_49fb;
+ const SPARSE_HEADER_MAGIC: u32 = 0xed26ff3a;
+
+ let mut magic4 = [0u8; 4];
+ match file.read_exact_at(&mut magic4[..], 0) {
+ Ok(()) => {}
+ Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(ImageType::Raw),
+ Err(e) => return Err(e),
+ }
+ if magic4 == QCOW_MAGIC.to_be_bytes() {
+ return Ok(ImageType::Qcow2);
+ }
+ if magic4 == SPARSE_HEADER_MAGIC.to_le_bytes() {
+ return Ok(ImageType::AndroidSparse);
+ }
+
+ let mut buf = [0u8; CDISK_MAGIC.len()];
+ match file.read_exact_at(buf.as_bytes_mut(), 0) {
+ Ok(()) => {}
+ Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(ImageType::Raw),
+ Err(e) => return Err(e),
+ }
+ if buf == CDISK_MAGIC.as_bytes() {
+ return Ok(ImageType::CompositeDisk);
+ }
+
+ Ok(ImageType::Raw)
}
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 5886535..0f41932 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -1045,8 +1045,9 @@
}
for disk in config.disks {
+ // Disk file locking is disabled because of missing SELinux policies.
command.arg("--block").arg(format!(
- "path={},ro={}",
+ "path={},ro={},lock=false",
add_preserved_fd(&mut preserved_fds, disk.image),
!disk.writable,
));
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
index 11a2115..99dc648 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
@@ -20,7 +20,12 @@
/** A label for the partition. */
@utf8InCpp String label;
- /** The backing file descriptor of the partition image. */
+ /**
+ * The backing file descriptor of the partition image.
+ *
+ * The image file must either be a raw binary file, or an android-sparse
+ * formatted file.
+ */
ParcelFileDescriptor image;
/** Whether the partition should be writable by the VM. */
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index f493202..be62d18 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -107,6 +107,7 @@
filesystems: microdroid_filesystem_images,
prebuilts: [
"rialto_bin",
+ "android_bootloader_crosvm_aarch64",
],
},
x86_64: {
@@ -125,6 +126,9 @@
default: [],
}),
filesystems: microdroid_filesystem_images,
+ prebuilts: [
+ "android_bootloader_crosvm_x86_64",
+ ],
},
},
binaries: [
@@ -138,7 +142,6 @@
"microdroid.json",
"microdroid_kernel",
"com.android.virt.init.rc",
- "android_bootloader_crosvm_aarch64",
] + select(soong_config_variable("ANDROID", "avf_microdroid_guest_gki_version"), {
"android15_66": [
"microdroid_gki-android15-6.6_initrd_debuggable",
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index cb21ccf..de1b081 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -78,7 +78,8 @@
private static final String TAG = "VirtualMachineConfig";
private static String[] EMPTY_STRING_ARRAY = {};
- private static final String U_BOOT_PREBUILT_PATH = "/apex/com.android.virt/etc/u-boot.bin";
+ private static final String U_BOOT_PREBUILT_PATH_ARM = "/apex/com.android.virt/etc/u-boot.bin";
+ private static final String U_BOOT_PREBUILT_PATH_X86 = "/apex/com.android.virt/etc/u-boot.rom";
// These define the schema of the config file persisted on disk.
// Please bump up the version number when adding a new key.
@@ -668,7 +669,11 @@
.orElse(null);
if (config.kernel == null && config.bootloader == null) {
- config.bootloader = openOrNull(new File(U_BOOT_PREBUILT_PATH), MODE_READ_ONLY);
+ if (Arrays.stream(Build.SUPPORTED_ABIS).anyMatch("x86_64"::equals)) {
+ config.bootloader = openOrNull(new File(U_BOOT_PREBUILT_PATH_X86), MODE_READ_ONLY);
+ } else {
+ config.bootloader = openOrNull(new File(U_BOOT_PREBUILT_PATH_ARM), MODE_READ_ONLY);
+ }
}
config.params =