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. Also we enabled hw timer interrupt and clock update before we call the option rom's init() funtion, so the clock tick update at BDA address 40:6C will work during the rom's init() execution. Withou this change, iPXE would hang on reading BDA 40:6C due to the value at this address is not changed.
Signed-off-by: Bin Gao gaobin@amazon.com --- src/fw/csm.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/src/fw/csm.c b/src/fw/csm.c index 8359bcb..f64bc73 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 @@ -219,6 +220,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) { @@ -240,11 +242,36 @@ handle_csm_0005(struct bregs *regs)
rom_reserve(rom->size * 512);
+ // callrom() typically calls the rom's init() functions. + // If the rom's init() function does a delay by detecting the value + // at address 40:6C, it will fail because the value at 40:6C is + // updated only in clock_update() which is called in hw timer ISR. + // Thus we have to enable hw timer interrupt and set up clock before + // calling callrom(). + pic_setup(); + timer_setup(); + clock_setup(); + // XX PnP seg/ofs should never be other than default callrom(rom, bdf);
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(3, "rom %p: not a PnP rom, no BEV or BCV capability\n", table); + } + regs->bx = 0; // FIXME regs->ax = 0; }