diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index 8edfeaacd7..b9b2d6c6d4 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -444,6 +444,25 @@ pub fn validate_block_device_sector_size(size: u32) -> Result<()> { Ok(()) } +/// Extra block device image to attach to the VM (e.g. CoCo addon, GPU addon). +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct ExtraImage { + /// Short name for this addon (e.g. "coco", "gpu"). Used as the virtio-blk + /// serial so the guest can discover the device via + /// `/dev/disk/by-id/virtio-addon-` and match kernel cmdline verity + /// params `kata.addon..verity_params=...`. + pub name: String, + + /// Path to the addon image file on the host. + #[serde(default)] + pub path: String, + + /// DM-verity parameters for this addon image (root_hash, salt, etc.). + /// Populated at install time from the image build artifacts. + #[serde(default)] + pub verity_params: String, +} + /// Guest kernel boot information. #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct BootInfo { @@ -484,6 +503,7 @@ pub struct BootInfo { /// - `virtio-blk-mmio` #[serde(default)] pub vm_rootfs_driver: String, + } impl BootInfo { @@ -1733,6 +1753,15 @@ pub struct Hypervisor { #[serde(default, flatten)] pub boot_info: BootInfo, + /// Additional block device images to attach to the VM (e.g. CoCo addon). + /// Each image is cold-plugged as a read-only virtio-blk device. + /// + /// This field lives on Hypervisor rather than BootInfo because + /// BootInfo is deserialized via `#[serde(flatten)]`, and the toml crate + /// does not forward TOML array-of-tables through a flatten boundary. + #[serde(default)] + pub extra_images: Vec, + /// Guest virtual CPU configuration information. #[serde(default, flatten)] pub cpu_info: CpuInfo, @@ -1842,6 +1871,9 @@ impl ConfigOps for Hypervisor { })?; hv.blockdev_info.adjust_config()?; hv.boot_info.adjust_config()?; + for extra in &mut hv.extra_images { + resolve_path!(extra.path, "extra image file {} is invalid: {}")?; + } hv.cpu_info.adjust_config()?; hv.debug_info.adjust_config()?; hv.device_info.adjust_config()?; @@ -1882,6 +1914,22 @@ impl ConfigOps for Hypervisor { let hv = conf.hypervisor.get(hypervisor).unwrap(); hv.blockdev_info.validate()?; hv.boot_info.validate()?; + for extra in &hv.extra_images { + validate_path!(extra.path, "extra image file {} is invalid: {}")?; + if extra.name.is_empty() { + return Err(std::io::Error::other( + "extra_images entry is missing required 'name' field", + )); + } + if !extra.verity_params.trim().is_empty() { + parse_kernel_verity_params(&extra.verity_params).map_err(|e| { + std::io::Error::other(format!( + "extra_images '{}' has invalid verity_params: {}", + extra.name, e + )) + })?; + } + } hv.cpu_info.validate()?; hv.debug_info.validate()?; hv.device_info.validate()?;