[PATCH 23/38] pci: Allow the video BIOS to work in SPL with QEMU
Simon Glass
sjg at chromium.org
Thu Mar 30 23:32:12 CEST 2023
QEMU emulates two common machines (Q35 and i440fx) which use mapping to
determine whether RAM is present below 1MB. In order to copy the video
BIOS to c0000 we need to flip this mapping over to RAM. This does not
happen automatically until SPL has finished running.
Switch in RAM at these address so that the video BIOS can be loaded and
run. This fix was found in the seabios code base.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
drivers/pci/pci_rom.c | 46 +++++++++++++++++++++++++++++++++++++++++++
include/pci_ids.h | 1 +
2 files changed, 47 insertions(+)
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index f0dfe6314907..0f44238bbbc8 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -141,6 +141,49 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp)
return 0;
}
+#define Q35_HOST_BRIDGE_PAM0 0x90
+#define I440FX_PAM0 0x59
+
+/**
+ * intel_set_writable_ram() - Set RAM to be writable
+ *
+ * This is needed for QEMU when using Q35 or I440FX emulation, since otherwise
+ * there is no RAM available at c0000
+ *
+ * See Intel 82945G/82945G/82945GC GMCH and 82945P/82945PL MCH Datasheet for
+ * information about the PAM0-PAM6 registers
+ */
+static void intel_set_writable_ram(void)
+{
+ struct udevice *dev;
+ int pam0 = -1;
+ int i;
+
+ for (pci_find_first_device(&dev); dev; pci_find_next_device(&dev)) {
+ const struct pci_child_plat *pdata = dev_get_parent_plat(dev);
+
+ if (pdata->vendor == PCI_VENDOR_ID_INTEL) {
+ if (pdata->device == PCI_DEVICE_ID_INTEL_Q35_MCH) {
+ pam0 = Q35_HOST_BRIDGE_PAM0;
+ break;
+ } else if (pdata->device == PCI_DEVICE_ID_INTEL_82441) {
+ pam0 = I440FX_PAM0;
+ break;
+ }
+ }
+ }
+
+ if (!dev)
+ return;
+
+ // Adjust RAM to be writable from c0000 to f0000
+ for (i = 1; i <= 6; i++)
+ dm_pci_write_config8(dev, pam0 + i, 0x33);
+
+ // Also f0000-100000
+ dm_pci_write_config8(dev, pam0, 0x30);
+}
+
/**
* pci_rom_load() - Load a ROM image and return a pointer to it
*
@@ -185,6 +228,9 @@ static int pci_rom_load(struct pci_rom_header *rom_header,
return -ENOMEM;
*allocedp = true;
#endif
+ /* QEMU hacks */
+ intel_set_writable_ram();
+
if (target != rom_header) {
ulong start = get_timer(0);
diff --git a/include/pci_ids.h b/include/pci_ids.h
index 5ae1b9b7fb6e..33e90c8d2769 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -2870,6 +2870,7 @@
#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
#define PCI_DEVICE_ID_INTEL_ICH9_AHCI 0x2922
+#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0
#define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18
#define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19
#define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a
--
2.40.0.348.gf938b09366-goog
More information about the U-Boot
mailing list