Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[efi] Work around platforms which choke on EFI_PCI_DEVICE_ENABLE
EFI_PCI_DEVICE_ENABLE is a list of the standard attributes that must
be enabled for a PCI device to function: I/O cycles, memory cycles,
and bus-mastering.  We currently call EFI_PCI_IO_PROTOCOL::Attribute()
with the parameter EFI_PCI_DEVICE_ENABLE to enable a PCI device.  This
should translate to a single write to PCI configuration space.

Simplicity is not a virtue within the UEFI world.  Some platforms will
'helpfully' report an error if EFI_PCI_DEVICE_ENABLE is used on a
device that doesn't actually support all three of the relevant
attributes.  For example, if a PCI device provides only memory-mapped
accesses (and so hardwires the I/O enable bit to zero), then using
EFI_PCI_DEVICE_ENABLE on such a platform will result in an
EFI_UNSUPPORTED error.

There is no plausible use case in which it is useful for the platform
to return an error in this way, and doing so makes it impossible to
distinguish genuine errors from noise.

Work around this broken behaviour by attempting to enable the three
attributes individually, and ignoring any errors.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed May 16, 2012
1 parent 73b2117 commit 1af9284
Showing 1 changed file with 12 additions and 10 deletions.
22 changes: 12 additions & 10 deletions src/interface/efi/efi_pci.c
Expand Up @@ -216,17 +216,19 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
*/
EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) {
EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
EFI_STATUS efirc;

/* Enable device */
if ( ( efirc = pci_io->Attributes ( pci_io,
EfiPciIoAttributeOperationSet,
EFI_PCI_DEVICE_ENABLE,
NULL ) ) != 0 ) {
DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n",
PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
return efirc;
}
/* Try to enable I/O cycles, memory cycles, and bus mastering.
* Some platforms will 'helpfully' report errors if these bits
* can't be enabled (for example, if the card doesn't actually
* support I/O cycles). Work around any such platforms by
* enabling bits individually and simply ignoring any errors.
*/
pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
EFI_PCI_IO_ATTRIBUTE_IO, NULL );
pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL );
pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL );

return 0;
}
Expand Down

0 comments on commit 1af9284

Please sign in to comment.