SeaBIOS 1.14 breaks Windows installation on non-bootable virtio disks

On my development laptop I could install Windows inside a libvirt/KVM VM without problems. When I tried the same on a different KVM host, Windows would refuse installation with the error message “Windows can’t be installed on this device”, inspite of the two VMs having absolutely identical settings.

Screenshot of Windows installer with error message
Windows installer with error message “Windows can’t be installed on this device”

When comparing the two hosts I found out that the other KVM host was using a newer Linux distribution with a newer QEMU version, so naturally this was my first suspect. But a QEMU downgrade wasn’t helping.

Further debugging showed that the SeaBIOS inside the VMs was also different: where SeaBIOS 1.12 and 1.13 on my laptop would work flawlessly, SeaBIOS 1.14 on the other host would not. So I cloned the SeaBIOS Git repo and through git bisect I found the responsible commit, 2f4d0686:

virtio: Do not init non-bootable devices

Because initializing a virtio-blk or virtio-scsi device requires a large
amount of memory, you cannot create more than about 10 virtio devices.
Since initialization is required for booting from media, we will not
initialize those devices that are not in the boot order list.

Signed-off-by: Alexey Kirillov 
Message-id: 20200107171917.7535-3-lekiravi@yandex-team.ru
Signed-off-by: Gerd Hoffmann 

Aha! So after this change a device had to be in the list of bootable devices in order for SeaBIOS to initialize it. And the Windows setup message, backed up by messages in the installer log file (you did know that Shift-F10 gives you a command window and that you can inspect X:\WINDOWS\Panther\setupact.log, right?) indicated that this wasn’t the case.

And indeed, this were part of my virt-install command line arguments:

  [...]
  --disk ${VM_NAME}.qcow2,size=50,bus=virtio \
  --disk ${WS_ISO},device=cdrom,boot_order=10 \
  --boot cdrom \
  [...]

This worked with SeaBIOS 1.13 because that version initialized all devices unconditionally. But after 2f4d0686, I needed to fix my command line arguments:

  [...]
  --disk ${VM_NAME}.qcow2,size=50,bus=virtio,boot_order=1 \
  --disk ${WS_ISO},device=cdrom,boot_order=10 \
  --boot cdrom \
  [...]

This makes sure that the emulated hard disk appears in the list of bootable devices, notably as the first one. And voila:

Screenshot of Windows installer now being happy
Windows installer now being happy