On physical hardware, some PCI devices are not detectable when UEFI BIOS invokes our InitializeYourself() function. But they are guaranteed to be available before UEFI invokes our PreparToBoot() function. So in the case of running CSM on physical hardware, we execute pci_probe_devices() at PrepareToBoot() stage.
Signed-off-by: Bin Gao gaobin@amazon.com --- src/fw/csm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/fw/csm.c b/src/fw/csm.c index 8359bcb..82d375c 100644 --- a/src/fw/csm.c +++ b/src/fw/csm.c @@ -63,7 +63,9 @@ static void csm_maininit(struct bregs *regs) { interface_init(); - pci_probe_devices(); + + if (CONFIG_CSM && CONFIG_QEMU_HARDWARE) + pci_probe_devices();
csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS; csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset(); @@ -143,6 +145,13 @@ handle_csm_0002(struct bregs *regs) return; }
+ // On physical hardware, some PCI devices are not detectable when + // UEFI invokes our InitializeYourself() function. But they + // are guaranteed to be available before UEFI invokes our + // PreparToBoot() function. + if (CONFIG_CSM && !CONFIG_QEMU_HARDWARE) + pci_probe_devices(); + dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
struct e820entry *p = (void *)csm_compat_table.E820Pointer;
On physical hardware especially server platforms, there are multiple root pci buses and they can exhaust all the pci bus numbers. So when scanning the pci bus, we need to allow the bus number up to 255. This only applies to CSM on physical hardware, not the case of CSM on QEMU.
Signed-off-by: Bin Gao gaobin@amazon.com --- src/hw/pcidevice.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c index 8853cf7..b36183f 100644 --- a/src/hw/pcidevice.c +++ b/src/hw/pcidevice.c @@ -26,6 +26,13 @@ pci_probe_devices(void) struct hlist_node **pprev = &PCIDevices.first; int extraroots = romfile_loadint("etc/extra-pci-roots", 0); int bus = -1, lastbus = 0, rootbuses = 0, count=0; + + // On physical hardware especially server platforms, there exists + // multiple pci roots, so the pci bus number could run up to the + // top value, i.e. 0xff + if (CONFIG_CSM && !CONFIG_QEMU_HARDWARE) + extraroots = 0xff; + while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) { bus++; int bdf;
Hi,
- // On physical hardware especially server platforms, there exists
- // multiple pci roots, so the pci bus number could run up to the
- // top value, i.e. 0xff
- if (CONFIG_CSM && !CONFIG_QEMU_HARDWARE)
extraroots = 0xff;
Reviewed-by: Gerd Hoffmann kraxel@redhat.com
cheers, Gerd
In csm mode, the bev pointer of the pci option rom was not added to the bootentry list, resulting in failure to boot from pci option rom. This patch fixed it.
Signed-off-by: Bin Gao gaobin@amazon.com --- src/fw/csm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/src/fw/csm.c b/src/fw/csm.c index 82d375c..3370fa5 100644 --- a/src/fw/csm.c +++ b/src/fw/csm.c @@ -19,6 +19,7 @@ #include "std/acpi.h" // RSDP_SIGNATURE #include "std/bda.h" // struct bios_data_area_s #include "std/optionrom.h" // struct rom_header +#include "std/pnpbios.h" // PNP_SIGNATURE #include "util.h" // copy_smbios
#define UINT8 u8 @@ -228,6 +229,7 @@ handle_csm_0005(struct bregs *regs) { EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx); struct rom_header *rom; + struct pnp_data *pnp; u16 bdf;
if (!CONFIG_OPTIONROMS) { @@ -254,6 +256,21 @@ handle_csm_0005(struct bregs *regs)
rom_confirm(rom->size * 512);
+ // PnP rom - check for BEV and BCV boot capabilities. + pnp = (void*)((u8*)rom + rom->pnpoffset); + if (pnp->signature == PNP_SIGNATURE) { + struct pci_device pci_dev = { + .bdf = bdf, + }; + int prio = csm_bootprio_pci(&pci_dev); + if (pnp->bev) + boot_add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, prio); + else if (pnp->bcv) + boot_add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, prio); + } else { + dprintf(1, "rom %p: not a PnP rom, no BEV or BCV capability\n", table); + } + regs->bx = 0; // FIXME regs->ax = 0; }
Hi,
- // PnP rom - check for BEV and BCV boot capabilities.
- pnp = (void*)((u8*)rom + rom->pnpoffset);
- if (pnp->signature == PNP_SIGNATURE) {
struct pci_device pci_dev = {
.bdf = bdf,
};
int prio = csm_bootprio_pci(&pci_dev);
if (pnp->bev)
boot_add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, prio);
else if (pnp->bcv)
boot_add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, prio);
- } else {
dprintf(1, "rom %p: not a PnP rom, no BEV or BCV capability\n", table);
- }
Reviewed-by: Gerd Hoffmann kraxel@redhat.com
cheers, Gerd
On Wed, Dec 18, 2019 at 11:04:26AM -0800, Bin Gao wrote:
On physical hardware, some PCI devices are not detectable when UEFI BIOS invokes our InitializeYourself() function. But they are guaranteed to be available before UEFI invokes our PreparToBoot() function. So in the case of running CSM on physical hardware, we execute pci_probe_devices() at PrepareToBoot() stage.
Hmm, I'm wondering whenever we can just move the pci_probe_devices() call unconditionally (i.e. do it for qemu too).
cheers, Gerd
On Thu, Dec 19, 2019 at 09:11:22AM +0100, Gerd Hoffmann wrote:
On Wed, Dec 18, 2019 at 11:04:26AM -0800, Bin Gao wrote:
On physical hardware, some PCI devices are not detectable when UEFI BIOS invokes our InitializeYourself() function. But they are guaranteed to be available before UEFI invokes our PreparToBoot() function. So in the case of running CSM on physical hardware, we execute pci_probe_devices() at PrepareToBoot() stage.
Hmm, I'm wondering whenever we can just move the pci_probe_devices() call unconditionally (i.e. do it for qemu too).
In QEMU/OVMF case, all PCI devices are already available before the first call InitializeYourself() comes from BIOS. So I think there is no need to apply this change to QEMU.
cheers, Gerd
On Thu, Dec 19, 2019 at 04:31:23PM -0800, Bin Gao wrote:
On Thu, Dec 19, 2019 at 09:11:22AM +0100, Gerd Hoffmann wrote:
On Wed, Dec 18, 2019 at 11:04:26AM -0800, Bin Gao wrote:
On physical hardware, some PCI devices are not detectable when UEFI BIOS invokes our InitializeYourself() function. But they are guaranteed to be available before UEFI invokes our PreparToBoot() function. So in the case of running CSM on physical hardware, we execute pci_probe_devices() at PrepareToBoot() stage.
Hmm, I'm wondering whenever we can just move the pci_probe_devices() call unconditionally (i.e. do it for qemu too).
In QEMU/OVMF case, all PCI devices are already available before the first call InitializeYourself() comes from BIOS. So I think there is no need to apply this change to QEMU.
Yes, it is not required. But I'd prefer to have both qemu and !qemu case run the same code paths if possible, so the question is whenever there are any bad side effects if we just move the call unconditionally ...
Given that this works fine on your physical hardware and all hardware initialization happens in the prepareforboot callback too I'd expect this should be ok, I can't see anything which depends on pci devices being initialized early in initializeyourself.
cheers, Gerd