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

Bin Meng bmeng.cn at gmail.com
Thu Jul 13 06:00:41 CEST 2023


Hi Simon,

On Mon, Jun 19, 2023 at 8:01 PM Simon Glass <sjg at chromium.org> wrote:
>
> 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();

I don't like inserting chip-specific logic in the generic codes.

The logic is already in qemu_chipset_init(). We should allow
qemu_chipset_init() to be called in the SPL.

> +
>         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
> --

Regards,
Bin


More information about the U-Boot mailing list