Qemu builder / qemuargs / access to cached ISO


I am currently unsuccessfully trying to build some images with qemu builder.
I use OVMF and consequently have to declare several -drive arguments to load each needed element. And obviously it requires to declare a -cdrom to access to the downloaded ISO, as it is not passed by Packer anymore.

Accessing the cached ISO is currently done with an “hardcoded” path to it: -cdrom", "${path.cwd}/packer_cache/a4672833d0d89d9d9953d44436c44a32e50994ed.iso" (see below for the full template).
I find this fragile and sub-efficient: if the Packer cache directory is changed, it would fail. If the ISO is changed, it would fail. Etc.

  • Is there a different way to obtain the cached ISO path (Packer variable?, finding a way to obtain the SHA1 of the cached ISO filename?, whatever?)?
  • Am I wrong and should I proceed differently?

Thanks for you inputs.

HCL template:

# Rocky Linux packer template

variable "image_checksum_url" {
  type    = string
  default = "file:https://download.rockylinux.org/pub/rocky/8/isos/x86_64/CHECKSUM"

variable "image_name" {
  type    = string
  default = "rocky-linux-8"

variable "image_url" {
  type    = string
  default = "https://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-8.4-x86_64-boot.iso"

variable "image_username" {
  description = "Unpriviledged user to create. Note: do not forget to adapt Kickstart file as well"
  type = string
  default = "rockylinux"

variable "ssh_private_key_file" {
  type    = string
  default = "${env("PACKER_PRIVATE_KEY")}"

source "qemu" "rockylinux" {
  boot_command           = [
    "<spacebar>ip=dhcp<spacebar>inst.text<spacebar>inst.ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/kickstart.cfg<wait>",
  boot_wait              = "60s"
  communicator           = "ssh"
  disk_compression       = true
  disk_interface         = "virtio"
  disk_size              = 8000
  format                 = "qcow2"
  http_directory         = "${var.image_name}/htdocs"
  iso_checksum           = "${var.image_checksum_url}"
  iso_url                = "${var.image_url}"
  net_device             = "virtio-net"
  output_directory       = "${path.cwd}/output-qemu"
  qemuargs               = [
	["-cdrom", "${path.cwd}/packer_cache/a4672833d0d89d9d9953d44436c44a32e50994ed.iso"],
    ["-drive", "file=${path.cwd}/output-qemu/${var.image_name}.qcow2,format=qcow2,if=virtio"],
	["-drive", "file=${path.cwd}/resources/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on"],
    ["-drive", "file=${path.cwd}/resources/testuefi_VARS.fd,if=pflash,format=raw,unit=1"],
    ["-m", "1024M"],
    ["-smp", "2"],
  shutdown_command       = "rm -rf /home/${var.image_username}/.ssh/authorized_keys && sudo rm -rf /root/.ssh/authorized_keys && echo 'packer' | sudo -S shutdown -P now"
  ssh_handshake_attempts = 200
  ssh_port               = 22
  ssh_private_key_file   = "${var.ssh_private_key_file}"
  ssh_timeout            = "30m"
  ssh_username           = "${var.image_username}"
  use_default_display    = true
  vm_name                = "${var.image_name}.qcow2"
  vnc_port_max           = 5910
  vnc_port_min           = 5910

build {
  sources = ["source.qemu.rockylinux"]

  provisioner "file" {
    destination = "/tmp"
    source      = "${var.image_name}/cloud-init"

  provisioner "shell" {
    execute_command = "chmod +x {{ .Path }}; sudo {{ .Path }}"
    scripts         = [


I’m not at the stage yet of thinking of passing UEFI to my build, as mine doesn’t even want to build, but I’m curious,

Where did you get the fd files from?
Why do you need two?
Why can’t you pass the firmware via the firmware option?