aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2018-11-20 08:06:55 +0100
committerGerd Hoffmann <kraxel@redhat.com>2019-05-22 08:01:20 +0200
commit0932c20560574696cf87ddd12623e8c423ee821b (patch)
tree26a78ce9c8e90175231950e7fe17c336c7b07285 /src
parent18d237b4e43ea24795f522c0aab1b4f54100ca80 (diff)
downloadseabios-0932c20560574696cf87ddd12623e8c423ee821b.tar.gz
optionrom: disallow int19 redirect for pnp roms.
Check whenever pnp roms attempt to redirect int19, and in case it does log a message and undo the redirect. A pnp rom should not need this, we have BEVs and BCVs for that. Nevertheless there are roms in the wild which are redirecting int19. At least some BIOS implementations for physical hardware have a config option in the setup to allow/disallow int19 redirections, so just not allowing this seems to be the way to deal with this situation. Buglink: https://bugzilla.redhat.com//show_bug.cgi?id=1642135 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Tested-by: Matt DeVillier <matt.devillier@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/optionroms.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/optionroms.c b/src/optionroms.c
index fc992f64..e906ab97 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -8,6 +8,7 @@
#include "bregs.h" // struct bregs
#include "config.h" // CONFIG_*
#include "farptr.h" // FLATPTR_TO_SEG
+#include "biosvar.h" // GET_IVT
#include "hw/pci.h" // pci_config_readl
#include "hw/pcidevice.h" // foreachpci
#include "hw/pci_ids.h" // PCI_CLASS_DISPLAY_VGA
@@ -308,6 +309,19 @@ fail:
return NULL;
}
+static int boot_irq_captured(void)
+{
+ return GET_IVT(0x19).segoff != FUNC16(entry_19_official).segoff;
+}
+
+static void boot_irq_restore(void)
+{
+ struct segoff_s seabios;
+
+ seabios = FUNC16(entry_19_official);
+ SET_IVT(0x19, seabios);
+}
+
// Attempt to map and initialize the option rom on a given PCI device.
static void
init_pcirom(struct pci_device *pci, int isvga, u64 *sources)
@@ -327,8 +341,18 @@ init_pcirom(struct pci_device *pci, int isvga, u64 *sources)
if (! rom)
// No ROM present.
return;
+ int irq_was_captured = boot_irq_captured();
+ struct pnp_data *pnp = get_pnp_rom(rom);
setRomSource(sources, rom, RS_PCIROM | (u32)pci);
init_optionrom(rom, pci->bdf, isvga);
+ if (boot_irq_captured() && !irq_was_captured &&
+ !file && !isvga && pnp) {
+ // This PCI rom is misbehaving - recapture the boot irqs
+ char *desc = MAKE_FLATPTR(FLATPTR_TO_SEG(rom), pnp->productname);
+ dprintf(1, "PnP optionrom \"%s\" (bdf %pP) captured int19, restoring\n",
+ desc, pci);
+ boot_irq_restore();
+ }
}