diff options
| author | Michael Brown | 2025-11-25 12:59:03 +0100 |
|---|---|---|
| committer | Michael Brown | 2025-11-25 13:04:43 +0100 |
| commit | 19dffdc836d0cbfd79ec475160e4a22600f67584 (patch) | |
| tree | 3eac9a83155db425084a2b509ae09813923de21a /src/interface/efi/efi_snp.c | |
| parent | [pci] Use runtime selectable PCI I/O API for EFI cloud builds (diff) | |
| download | ipxe-19dffdc836d0cbfd79ec475160e4a22600f67584.tar.gz ipxe-19dffdc836d0cbfd79ec475160e4a22600f67584.tar.xz ipxe-19dffdc836d0cbfd79ec475160e4a22600f67584.zip | |
[efi] Allow for creating devices with no EFI parent device
On some systems (observed on an AWS m8g.medium instance in eu-west-2),
the UEFI firmware fails to enumerate some of the underlying hardware
devices. On these systems, we cannot comply with the UEFI device
model by adding our SNP device as a child of the hardware device and
appending to the parent hardware device path, since no parent hardware
device has been created.
Work around these systems by allowing for the creation of SNP devices
with no parent device.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_snp.c')
| -rw-r--r-- | src/interface/efi/efi_snp.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 88334c8d0..86ad87bde 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -1792,14 +1792,6 @@ static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) { EFI_STATUS efirc; int rc; - /* Find parent EFI device */ - efidev = efidev_parent ( netdev->dev ); - if ( ! efidev ) { - DBG ( "SNP skipping non-EFI device %s\n", netdev->name ); - rc = 0; - goto err_no_efidev; - } - /* Allocate the SNP device */ snpdev = zalloc ( sizeof ( *snpdev ) ); if ( ! snpdev ) { @@ -1807,9 +1799,13 @@ static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) { goto err_alloc_snp; } snpdev->netdev = netdev_get ( netdev ); - snpdev->efidev = efidev; INIT_LIST_HEAD ( &snpdev->rx ); + /* Find parent EFI device, if any */ + efidev = efidev_parent ( netdev->dev ); + if ( efidev ) + snpdev->parent = efidev->device; + /* Sanity check */ if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) { DBGC ( snpdev, "SNPDEV %p cannot support link-layer address " @@ -1931,8 +1927,10 @@ static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) { goto err_open_nii31; } - /* Add as child of EFI parent device */ - if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) { + /* Add as child of EFI parent device, if applicable */ + if ( snpdev->parent && + ( ( rc = efi_child_add ( snpdev->parent, + snpdev->handle ) ) != 0 ) ) { DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n", snpdev, efi_handle_name ( efidev->device ), strerror ( rc ) ); @@ -1959,7 +1957,8 @@ static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) { list_del ( &snpdev->list ); if ( snpdev->package_list ) leak |= efi_snp_hii_uninstall ( snpdev ); - efi_child_del ( efidev->device, snpdev->handle ); + if ( snpdev->parent ) + efi_child_del ( snpdev->parent, snpdev->handle ); err_efi_child_add: efi_close_by_driver ( snpdev->handle, &efi_nii31_protocol_guid ); err_open_nii31: @@ -1996,7 +1995,6 @@ static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) { free ( snpdev ); } err_alloc_snp: - err_no_efidev: if ( leak ) DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev ); return rc; @@ -2051,7 +2049,8 @@ static void efi_snp_remove ( struct net_device *netdev, void *priv __unused ) { list_del ( &snpdev->list ); if ( snpdev->package_list ) leak |= efi_snp_hii_uninstall ( snpdev ); - efi_child_del ( snpdev->efidev->device, snpdev->handle ); + if ( snpdev->parent ) + efi_child_del ( snpdev->parent, snpdev->handle ); efi_close_by_driver ( snpdev->handle, &efi_nii_protocol_guid ); efi_close_by_driver ( snpdev->handle, &efi_nii31_protocol_guid ); if ( ( ! efi_shutdown_in_progress ) && |
