diff --git a/osdk/src/bundle/mod.rs b/osdk/src/bundle/mod.rs index 9a0f19bd..27da172d 100644 --- a/osdk/src/bundle/mod.rs +++ b/osdk/src/bundle/mod.rs @@ -219,17 +219,30 @@ impl Bundle { BootMethod::GrubRescueIso => { let vm_image = self.manifest.vm_image.as_ref().unwrap(); assert!(matches!(vm_image.typ(), AsterVmImageType::GrubIso(_))); + let bootdev_opts = action + .qemu + .bootdev_append_options + .as_deref() + .unwrap_or(",index=2,media=cdrom"); qemu_cmd.arg("-drive").arg(format!( - "file={},index=2,media=cdrom", - self.path.join(vm_image.path()).to_string_lossy() + "file={},format=raw{}", + self.path.join(vm_image.path()).to_string_lossy(), + bootdev_opts, )); } BootMethod::GrubQcow2 => { let vm_image = self.manifest.vm_image.as_ref().unwrap(); assert!(matches!(vm_image.typ(), AsterVmImageType::Qcow2(_))); + // FIXME: this doesn't work for regular QEMU, but may work for TDX. + let bootdev_opts = action + .qemu + .bootdev_append_options + .as_deref() + .unwrap_or(",if=virtio"); qemu_cmd.arg("-drive").arg(format!( - "file={},index=0,media=disk,format=qcow2", - self.path.join(vm_image.path()).to_string_lossy() + "file={},format=qcow2{}", + self.path.join(vm_image.path()).to_string_lossy(), + bootdev_opts, )); } }; diff --git a/osdk/src/cli.rs b/osdk/src/cli.rs index 74df138b..fab56ccd 100644 --- a/osdk/src/cli.rs +++ b/osdk/src/cli.rs @@ -309,6 +309,13 @@ pub struct CommonArgs { global = true )] pub boot_method: Option, + #[arg( + long = "bootdev-append-options", + help = "Additional QEMU `-drive` options for the boot device", + value_name = "OPTIONS", + global = true + )] + pub bootdev_append_options: Option, #[arg( long = "display-grub-menu", help = "Display the GRUB menu if booting with GRUB", diff --git a/osdk/src/config/mod.rs b/osdk/src/config/mod.rs index 40dbe206..dea0b64f 100644 --- a/osdk/src/config/mod.rs +++ b/osdk/src/config/mod.rs @@ -72,6 +72,9 @@ fn apply_args_before_finalize(action_scheme: &mut ActionScheme, args: &CommonArg if let Some(path) = &args.qemu_exe { qemu.path = Some(path.clone()); } + if let Some(bootdev_options) = &args.bootdev_append_options { + qemu.bootdev_append_options = Some(bootdev_options.clone()); + } } } diff --git a/osdk/src/config/scheme/qemu.rs b/osdk/src/config/scheme/qemu.rs index 1a19200e..3b307aa9 100644 --- a/osdk/src/config/scheme/qemu.rs +++ b/osdk/src/config/scheme/qemu.rs @@ -16,6 +16,20 @@ pub struct QemuScheme { /// The additional arguments for running QEMU, in the form of raw /// command line arguments. pub args: Option, + /// The additional qemu argument after the `-drive` option for the + /// boot device, in the form of raw command line arguments, comma + /// included. For example, `",if=virtio,media=disk,index=2"`. + /// The `format` and the `file` options are not allowed to set. + /// + /// This option only works with [`super::BootMethod::GrubQcow2`] and + /// [`super::BootMethod::GrubRescueIso`]. + /// + /// This option exist because different firmwares may need + /// different interface types for the boot drive. + /// + /// See + /// for details about `-drive` option. + pub bootdev_append_options: Option, /// The path of qemu pub path: Option, } @@ -23,6 +37,11 @@ pub struct QemuScheme { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Qemu { pub args: String, + /// This finalized config has a unorthodox `Option` because + /// we cannot provide a default value for it. The default + /// value is determined by the final running routine + /// [`crate::bundle::Bundle::run`]. + pub bootdev_append_options: Option, pub path: PathBuf, } @@ -30,6 +49,7 @@ impl Default for Qemu { fn default() -> Self { Qemu { args: String::new(), + bootdev_append_options: None, path: PathBuf::from(get_default_arch().system_qemu()), } } @@ -63,6 +83,7 @@ impl QemuScheme { pub fn finalize(self, arch: Arch) -> Qemu { Qemu { args: self.args.unwrap_or_default(), + bootdev_append_options: self.bootdev_append_options, path: self.path.unwrap_or(PathBuf::from(arch.system_qemu())), } }