All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomita Moeko <tomitamoeko@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Alex Williamson" <alex@shazbot.org>,
	"Cédric Le Goater" <clg@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Tomita Moeko" <tomitamoeko@gmail.com>,
	"K S Maan" <kirandeepmaan45@gmail.com>
Subject: [PATCH v5 2/3] vfio/igd: Patch device ID for romfile-provided VBIOS
Date: Tue,  7 Jul 2026 16:35:49 +0800	[thread overview]
Message-ID: <20260707083550.25765-3-tomitamoeko@gmail.com> (raw)
In-Reply-To: <20260707083550.25765-1-tomitamoeko@gmail.com>

Multiple IGD devices of the same generation share the same rom,
the device ID in its PCIR structure may not match. As SeaBIOS checks
the device ID strictly and refuses to run the VBIOS on a mismatch,
the ID has to be patched.

For a ROM read from the kernel ROM BAR, vfio_pci_load_rom() already
patches the device ID and recomputes the checksum. A VBIOS provided by
the user via romfile, however, is loaded by the generic PCI core and
does not receive this IGD-specific fixup.

Introduce vfio_igd_legacy_rom_quirk() in igd.c, which patches the
device ID and recomputes the (known bogus) checksum of a Gen 6-9 IGD
legacy VBIOS. This is registered as romfile_fixup hook when a romfile
is configured so that the romfile-provided VBIOS then receives the
same fixup as one read from the kernel ROM BAR.

Reported-by: K S Maan <kirandeepmaan45@gmail.com>
Signed-off-by: Tomita Moeko <tomitamoeko@gmail.com>
---
 hw/vfio/igd-stubs.c  |  5 +++++
 hw/vfio/igd.c        | 53 ++++++++++++++++++++++++++++++++++++++++++++
 hw/vfio/pci.h        |  2 ++
 hw/vfio/trace-events |  1 +
 4 files changed, 61 insertions(+)

diff --git a/hw/vfio/igd-stubs.c b/hw/vfio/igd-stubs.c
index f7687d9091..29110f7568 100644
--- a/hw/vfio/igd-stubs.c
+++ b/hw/vfio/igd-stubs.c
@@ -18,3 +18,8 @@ bool vfio_probe_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
 {
     return true;
 }
+
+void vfio_igd_legacy_rom_quirk(PCIDevice *pdev, uint8_t *ptr, uint32_t size)
+{
+    return;
+}
diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
index e091f21b6a..a5c1b57ce4 100644
--- a/hw/vfio/igd.c
+++ b/hw/vfio/igd.c
@@ -610,6 +610,10 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
         goto error;
     }
 
+    if (pdev->romfile) {
+        pdev->romfile_fixup = vfio_igd_legacy_rom_quirk;
+    }
+
     /*
      * ASLS (OpRegion address) is read-only, emulated
      * It contains HPA, guest firmware need to reprogram it with GPA.
@@ -724,3 +728,52 @@ bool vfio_probe_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
 
     return vfio_pci_igd_config_quirk(vdev, errp);
 }
+
+void vfio_igd_legacy_rom_quirk(PCIDevice *pdev, uint8_t *ptr, uint32_t size)
+{
+    VFIOPCIDevice *vdev = VFIO_PCI_DEVICE(pdev);
+    int gen;
+    uint16_t pcir_offset;
+    uint8_t checksum = 0;
+    uint32_t i;
+
+    if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
+        !vfio_is_vga(vdev) || !vdev->vga) {
+        return;
+    }
+
+    /* Only Gen 6~9 devices have legacy VBIOS as Option ROM */
+    gen = igd_gen(vdev);
+    if (gen < 6 || gen > 9) {
+        return;
+    }
+
+    if (pci_get_word(ptr) != 0xaa55) {
+        return;
+    }
+
+    /* Must be a legacy ROM */
+    pcir_offset = pci_get_word(ptr + 0x18);
+    if (pcir_offset + 0x14 >= size || memcmp(ptr + pcir_offset, "PCIR", 4) ||
+        pci_get_byte(ptr + pcir_offset + 0x14) != 0x00) {
+        return;
+    }
+
+    /*
+     * Patch device ID as multiple IGD devices share the same rom with possible
+     * non-matching IDs. This duplicates with vfio_pci_load_rom(), but required
+     * for romfile.
+     */
+    pci_set_word(ptr + pcir_offset + 6, vdev->device_id);
+
+    /*
+     * IGD roms are known to have bogus checksums. No matter we changed the
+     * device ID or not, we need to recalculate the checksum and patch it.
+     */
+    for (i = 0; i < size; i++) {
+        checksum += ptr[i];
+    }
+    ((uint8_t *)ptr)[6] -= checksum;
+
+    trace_vfio_pci_igd_vbios_patched(vdev->vbasedev.name);
+}
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index cf56711587..65a1385ce3 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -253,8 +253,10 @@ void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
 bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
 void vfio_quirk_reset(VFIOPCIDevice *vdev);
 VFIOQuirk *vfio_quirk_alloc(int nr_mem);
+
 void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr);
 bool vfio_probe_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp);
+void vfio_igd_legacy_rom_quirk(PCIDevice *pdev, uint8_t *ptr, uint32_t size);
 
 extern const PropertyInfo qdev_prop_nv_gpudirect_clique;
 
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 4c28b3291c..e472a65a44 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -90,6 +90,7 @@ vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_
 vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB"
 vfio_pci_igd_host_bridge_enabled(const char *name) "%s"
 vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s"
+vfio_pci_igd_vbios_patched(const char *name) "%s"
 
 # listener.c
 vfio_iommu_map_notify(const char *op, uint64_t iova_start, uint64_t iova_end) "iommu %s @ 0x%"PRIx64" - 0x%"PRIx64
-- 
2.53.0



  parent reply	other threads:[~2026-07-07  8:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  8:35 [PATCH v5 0/3] vfio/igd: Fix garbled screen on IGD passthrough with legacy VBIOS Tomita Moeko
2026-07-07  8:35 ` [PATCH v5 1/3] hw/pci: Introduce romfile_fixup hook in PCIDevice Tomita Moeko
2026-07-07  8:35 ` Tomita Moeko [this message]
2026-07-07  8:35 ` [PATCH v5 3/3] vfio/igd: Clear saved BDSM in legacy VBIOS ROM at load time Tomita Moeko
2026-07-07 12:47 ` [PATCH v5 0/3] vfio/igd: Fix garbled screen on IGD passthrough with legacy VBIOS K S Maan
2026-07-08  4:31 ` Alex Williamson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707083550.25765-3-tomitamoeko@gmail.com \
    --to=tomitamoeko@gmail.com \
    --cc=alex@shazbot.org \
    --cc=clg@redhat.com \
    --cc=kirandeepmaan45@gmail.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.