소스 검색

[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>
tags/v1.20.1
Michael Brown 12 년 전
부모
커밋
1af9284225
1개의 변경된 파일12개의 추가작업 그리고 10개의 파일을 삭제
  1. 12
    10
      src/interface/efi/efi_pci.c

+ 12
- 10
src/interface/efi/efi_pci.c 파일 보기

@@ -216,17 +216,19 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
216 216
  */
217 217
 EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) {
218 218
 	EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
219
-	EFI_STATUS efirc;
220 219
 
221
-	/* Enable device */
222
-	if ( ( efirc = pci_io->Attributes ( pci_io,
223
-					    EfiPciIoAttributeOperationSet,
224
-					    EFI_PCI_DEVICE_ENABLE,
225
-					    NULL ) ) != 0 ) {
226
-		DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n",
227
-		       PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
228
-		return efirc;
229
-	}
220
+	/* Try to enable I/O cycles, memory cycles, and bus mastering.
221
+	 * Some platforms will 'helpfully' report errors if these bits
222
+	 * can't be enabled (for example, if the card doesn't actually
223
+	 * support I/O cycles).  Work around any such platforms by
224
+	 * enabling bits individually and simply ignoring any errors.
225
+	 */
226
+	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
227
+			     EFI_PCI_IO_ATTRIBUTE_IO, NULL );
228
+	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
229
+			     EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL );
230
+	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
231
+			     EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL );
230 232
 
231 233
 	return 0;
232 234
 }

Loading…
취소
저장