summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_snp.c
diff options
context:
space:
mode:
authorMichael Brown2025-11-25 12:59:03 +0100
committerMichael Brown2025-11-25 13:04:43 +0100
commit19dffdc836d0cbfd79ec475160e4a22600f67584 (patch)
tree3eac9a83155db425084a2b509ae09813923de21a /src/interface/efi/efi_snp.c
parent[pci] Use runtime selectable PCI I/O API for EFI cloud builds (diff)
downloadipxe-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.c27
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 ) &&