vmm, devices: Add fw_cfg string item support

QEMU supports passing inline string values to the guest via fw_cfg
(-fw_cfg name=...,string=...). Cloud Hypervisor previously only
supported file-backed fw_cfg items. This adds the 'string' option
so users can pass values like OVMF's X-PciMmio64Mb without creating
a temporary file on the host.

Each fw_cfg item now accepts exactly one of 'file' or 'string'.
The FwCfgInvalidItem invariant is validated in PayloadConfig::validate()
(via FwCfgConfig::validate()), covering both CLI and JSON API paths.
The populate_fw_cfg match arm uses unreachable!() since validation
guarantees the invariant holds at that point.

CLI syntax:
  --fw-cfg-config items=[name=opt/ovmf/X-PciMmio64Mb,string=262144]

Signed-off-by: Keith Adler <kadler@cloudflare.com>
This commit is contained in:
Keith Adler
2026-04-14 14:48:49 -05:00
committed by Rob Bradford
parent e4e3375a8d
commit 926dd1e141
6 changed files with 209 additions and 24 deletions

View File

@@ -11538,4 +11538,45 @@ mod fw_cfg {
handle_child_output(r, &output);
}
#[test]
#[cfg_attr(feature = "mshv", ignore = "See #7434")]
fn test_fw_cfg_string() {
let disk_config = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(disk_config));
let mut cmd = GuestCommand::new(&guest);
let kernel_path = direct_kernel_boot_path();
let cmd_line = DIRECT_KERNEL_BOOT_CMDLINE;
cmd.args(["--cpus", "boot=4"])
.default_memory()
.args(["--kernel", kernel_path.to_str().unwrap()])
.args(["--cmdline", cmd_line])
.default_disks()
.default_net()
.args([
"--fw-cfg-config",
"initramfs=off,items=[name=opt/org.test/test-string,string=hello-from-vmm]",
])
.capture_output();
let mut child = cmd.spawn().unwrap();
let r = std::panic::catch_unwind(|| {
guest.wait_vm_boot().unwrap();
thread::sleep(std::time::Duration::new(3, 0));
let result = guest
.ssh_command(
"sudo cat /sys/firmware/qemu_fw_cfg/by_name/opt/org.test/test-string/raw",
)
.unwrap();
assert_eq!(result, "hello-from-vmm");
});
kill_child(&mut child);
let output = child.wait_with_output().unwrap();
handle_child_output(r, &output);
}
}