[PATCH v4 6/6] xen/igd: use custom option ROM if provided
Chuck Zmudzinski <[email protected]> Fri, 31 Jul 2026 20:17:30 -0400
| Newsgroups | gmane.comp.emulators.xen.devel,gmane.comp.emulators.qemu,gmane.comp.emulators.qemu.stable |
|---|---|
| Message-ID | <[email protected]> |
Since in some cases the option ROM is not readable from sysfs on the host, provide the option to use a custom option ROM file instead that, for example, could be extracted from BIOS or UEFI firmware and modified as needed for use with a particular Intel IGD device. The file must be named "igd.rom" and be located in a directory configured at build time as a Qemu firmware directory and its size should be a power of two, and it must be compatible with the particular Intel IGD device being passed through. If provided, the "igd.rom" file will be used as the option ROM instead of the option ROM file epxosed in the host sysfs. If no "igd.rom" file is provided, this patch has no effect. Signed-off-by: Chuck Zmudzinski <[email protected]> --- Changes in v4: - v4 is the first version of the series that has this patch Sorry for the length of these notes but there are many things to say about this patch that are not obvious to persons without some experience of actually trying to use the option ROM of an Intel IGD when it is passed through to a Xen HVM guest. This patch is primarily for providing a way to add Intel IGD support for the OvmfXen platform to get graphics output during early boot from modern Intel IGD devices that are only compatible with UEFI for graphics output during early boot. Note this patch is not necessary for successful operation of the Intel IGD in the guest once the guest OS drivers have loaded. It is only needed as part of the patchset necessary to provide graphics output from the Intel IGD in the guest during early boot when using newer devices that are only compatible with UEFI for graphics output during early boot. Most older devices that are compatible with legacy VGA BIOS will work with Seabios without this patch, but they will need Patch 3 of this patchset to work with Seabios. Some notes on adding Intel IGD support for the OvmfXen platform: It is necessary to provide an EFI graphics output protocol (GOP) driver to the guest to get output from the Intel IGD before the guest OS loads the graphics drivers when the guest uses UEFI. This GOP driver is essentially the replacement of the VBIOS driver that applied to older devices that use legacy bios, as described here: https://www.intel.com/content/www/us/en/support/articles/000005749/graphics.html Unfortunately, with modern Intel IGD devices, the EFI GOP driver is not provided to the guest in the usual way of providing firmware for a PCI device in the option ROM of the real PCI device. So I included this patch in this patchset to provide a way to expose the EFI GOP driver to the guest. I was able to extract the GOP driver for my device using the UEFI bios update file from the motherboard manufacturer and the UEFITool available here: https://github.com/longsoft/uefitool That EFI driver can be wrapped into an option ROM using the EfiRom bin wrapper that is part of the edk2 project: https://github.com/tianocore/edk2/blob/master/BaseTools/BinWrappers/PosixLike/EfiRom I tried setting the 'romfile' member of the PCIDevice struct that is used by KVM/VFIO Qemu devices and emulated Qemu PCI devices, but that did not work with Xen PCI passthrough devices. Neither Seabios nor the OvmfXen platform could detect the option ROM in the guest with that method of exposing an option ROM to the guest. So I implemented this approach of substituting the 'rom' file exposed by sysfs with an administrator-provided file instead of using 'romfile'. In the commit message I mentioned the size of the rom file "should" be a power of two. I mentioned this because the code in pci.c that handles the 'romfile' setting for PCI devices enforces this requirement strictly on the romfile that Qemu emulated or VFIO devices use. However, I do not know for sure whether or not the rom file is strictly required to have a size of a power of two, so that is why I say it should be a power of two. In my testing, I zero pad the "igd.rom" file so it has a size of a power of two. I will accept the suggestions of experts on this question about the appropriate size of the option ROM file (I am not such an expert!). As mentioned in the message accompanying Patch 4 of this patchset, the official edk2 project does not provide support for the Intel IGD, but some OVMF patches for Intel IGD support are available online for KVM/VFIO guests, such as at the links below (they apply to the OvmfPkgX64 platform): https://github.com/cmd2001/build-edk2-gvtd https://eci.intel.com/docs/3.3/components/kvm-hypervisor.html#build-ovmf-fd-for-kvm https://github.com/LongQT-sea/intel-igpu-passthru With such patches it is reported that the passed through Intel IGD device lights up the display during early boot from OVMF and the guest bootloader in KVM/VFIO guests provided that the administrator provides the correct ROM file via the 'romfile' setting for the passed thorugh Intel iGD device and applies appropriate patches to the OvmfPkgX64 platform. It should also be possible to add Intel IGD support for the OvmfXen platform also but I have not seen any such patches online for OvmfXen and if anyone knows of such patches online I would be interested to be informed about them. I am also working on my own patches to add Intel IGD support to the OvmfXen platform, in private for now. If anyone is interested, I can make the work I have done so far toward this goal avalable online. hw/xen/xen_pt_load_rom.c | 47 +++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c index eaf0ae1..6c2aa8f 100644 --- a/hw/xen/xen_pt_load_rom.c +++ b/hw/xen/xen_pt_load_rom.c @@ -2,6 +2,7 @@ * This is splited from hw/i386/kvm/pci-assign.c */ #include "qemu/osdep.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/pci/pci.h" @@ -13,9 +14,9 @@ * need to be modified. * * For such cases, use this function to get a pointer to the option ROM - * from sysfs. Caller has the responsibility to edit the option ROM as - * needed, call pci_register_bar to register the modified option ROM, - * and set has_rom to true for the PCI device. + * from a user provided romfile or sysfs. Caller has the responsibility + * to edit the option ROM as needed, call pci_register_bar to register + * the modified option ROM, and set has_rom to true for the PCI device. * * This function must be called before xen_pt_register_regions is called * because if xen_pt_register_regions is called first, it will register @@ -32,17 +33,27 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct stat st; void *ptr = NULL; Object *owner = OBJECT(dev); + g_autofree const char *fname = g_strdup("igd.rom"); + g_autofree const char *path = qemu_find_file(QEMU_FILE_TYPE_BIOS, fname); + bool sysfs = false; /* If loading ROM from file, pci handles it */ if (dev->romfile || !dev->rom_bar) { return NULL; } - snprintf(rom_file, sizeof(rom_file), - "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", - domain, bus, slot, function); + if (path) { + snprintf(rom_file, sizeof(rom_file), "%s", path); + XEN_PT_LOG(dev, "Using Intel IGD romfile %s " + "(administratior provided)\n", path); + } else { + snprintf(rom_file, sizeof(rom_file), + "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", + domain, bus, slot, function); + sysfs = true; + XEN_PT_LOG(dev, "Using Intel IGD romfile from host sysfs\n"); + } - /* Write "1" to the ROM file to enable it */ fp = fopen(rom_file, "r+"); if (fp == NULL) { if (errno != ENOENT) { @@ -55,10 +66,14 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, goto close_rom; } - val = 1; - if (fwrite(&val, 1, 1, fp) != 1) { - goto close_rom; + /* Write "1" to the ROM file to enable it if using ROM from sysfs */ + if (sysfs) { + val = 1; + if (fwrite(&val, 1, 1, fp) != 1) { + goto close_rom; + } } + fseek(fp, 0, SEEK_SET); if (dev->romsize != UINT_MAX) { @@ -83,11 +98,13 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, *size = st.st_size; close_rom: - /* Write "0" to disable ROM */ - fseek(fp, 0, SEEK_SET); - val = 0; - if (!fwrite(&val, 1, 1, fp)) { - XEN_PT_WARN(dev, "%s\n", "Failed to disable pci-sysfs rom file"); + /* Write "0" to disable ROM if using ROM from sysfs */ + if (sysfs) { + fseek(fp, 0, SEEK_SET); + val = 0; + if (!fwrite(&val, 1, 1, fp)) { + XEN_PT_WARN(dev, "%s\n", "Failed to disable pci-sysfs rom file"); + } } fclose(fp); -- 2.52.0