[PATCH v4 22/45] pci: Allow the video BIOS to work in SPL with QEMU

Simon Glass sjg at chromium.org
Mon Jun 19 13:59:37 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>
---

(no changes since v1)

 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 88b0a6404585..856d53264114 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.41.0.162.gfafddb0af9-goog



More information about the U-Boot mailing list