diff --git a/src/arch/x86/prefix/efidrvprefix.c b/src/arch/x86/prefix/efidrvprefix.c index 280e33535..3daefd00a 100644 --- a/src/arch/x86/prefix/efidrvprefix.c +++ b/src/arch/x86/prefix/efidrvprefix.c @@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include /** * EFI entry point @@ -43,8 +42,5 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle, initialise(); startup(); - /* Release network devices for use via SNP */ - efi_snp_release(); - return 0; } diff --git a/src/arch/x86/prefix/efiprefix.c b/src/arch/x86/prefix/efiprefix.c index a0347680c..b0bf99c65 100644 --- a/src/arch/x86/prefix/efiprefix.c +++ b/src/arch/x86/prefix/efiprefix.c @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @@ -45,6 +46,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle, /* Record autoboot device (if any) */ efi_set_autoboot(); + /* Claim SNP devices for use by iPXE */ + efi_snp_claim(); + /* Call to main() */ if ( ( rc = main() ) != 0 ) { efirc = EFIRC ( rc ); @@ -52,6 +56,7 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle, } err_main: + efi_snp_release(); efi_loaded_image->Unload ( image_handle ); efi_driver_reconnect_all(); err_init: diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h index 06483cfbc..87798ccc2 100644 --- a/src/include/ipxe/efi/efi_snp.h +++ b/src/include/ipxe/efi/efi_snp.h @@ -78,7 +78,22 @@ extern int efi_snp_hii_install ( struct efi_snp_device *snpdev ); extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ); extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle ); extern struct efi_snp_device * last_opened_snpdev ( void ); -extern void efi_snp_claim ( void ); -extern void efi_snp_release ( void ); +extern void efi_snp_set_claimed ( int claimed ); + +/** + * Claim network devices for use by iPXE + * + */ +static inline void efi_snp_claim ( void ) { + efi_snp_set_claimed ( 1 ); +} + +/** + * Release network devices for use via SNP + * + */ +static inline void efi_snp_release ( void ) { + efi_snp_set_claimed ( 0 ); +} #endif /* _IPXE_EFI_SNP_H */ diff --git a/src/interface/efi/efi_download.c b/src/interface/efi/efi_download.c index 80279f7f9..522276ace 100644 --- a/src/interface/efi/efi_download.c +++ b/src/interface/efi/efi_download.c @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** iPXE download protocol GUID */ @@ -63,6 +64,8 @@ static void efi_download_close ( struct efi_download_file *file, int rc ) { file->finish_callback ( file->context, EFIRC ( rc ) ); intf_shutdown ( &file->xfer, rc ); + + efi_snp_release(); } /** @@ -147,6 +150,7 @@ efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused, return EFIRC ( rc ); } + efi_snp_claim(); file->pos = 0; file->data_callback = DataCallback; file->finish_callback = FinishCallback; diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index fd3aad4cb..a301f3b48 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -67,6 +67,9 @@ static EFI_GUID efi_load_file_protocol_guid /** List of SNP devices */ static LIST_HEAD ( efi_snp_devices ); +/** Network devices are currently claimed for use by iPXE */ +static int efi_snp_claimed; + /** * Set EFI SNP mode state * @@ -83,7 +86,7 @@ static void efi_snp_set_state ( struct efi_snp_device *snpdev ) { } else if ( ! netdev_is_open ( netdev ) ) { /* Network device not opened; report as Started */ mode->State = EfiSimpleNetworkStarted; - } else if ( ! netdev_rx_frozen ( netdev ) ) { + } else if ( efi_snp_claimed ) { /* Network device opened but claimed for use by iPXE; report * as Started to inhibit receive polling. */ @@ -162,7 +165,7 @@ efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; snpdev->started = 1; @@ -184,7 +187,7 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; snpdev->started = 0; @@ -212,7 +215,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, ( ( unsigned long ) extra_tx_bufsize ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { @@ -242,7 +245,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { snpdev, ( ext_verify ? "with" : "without" ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; netdev_close ( snpdev->netdev ); @@ -272,7 +275,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; netdev_close ( snpdev->netdev ); @@ -309,7 +312,7 @@ efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable, } /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Lie through our teeth, otherwise MNP refuses to accept us */ @@ -335,7 +338,7 @@ efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, ( reset ? "reset" : ll_protocol->ntoa ( new ) ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Set the MAC address */ @@ -372,7 +375,7 @@ efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset, ( reset ? " reset" : "" ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Gather statistics */ @@ -424,7 +427,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Try to hash the address */ @@ -461,7 +464,7 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read, DBGC2_HDA ( snpdev, offset, data, len ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; return EFI_UNSUPPORTED; @@ -484,7 +487,7 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Poll the network device */ @@ -583,7 +586,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC2 ( snpdev, "\n" ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Sanity checks */ @@ -695,7 +698,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, ( ( unsigned long ) *len ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return EFI_NOT_READY; /* Poll the network device */ @@ -759,7 +762,7 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event, return; /* Do nothing if net device is currently claimed for use by iPXE */ - if ( ! netdev_rx_frozen ( snpdev->netdev ) ) + if ( efi_snp_claimed ) return; /* Poll the network device */ @@ -1184,23 +1187,17 @@ struct efi_snp_device * last_opened_snpdev ( void ) { } /** - * Claim network devices for use by iPXE + * Set SNP claimed/released state * + * @v claimed Network devices are claimed for use by iPXE */ -void efi_snp_claim ( void ) { - struct net_device *netdev; +void efi_snp_set_claimed ( int claimed ) { + struct efi_snp_device *snpdev; - for_each_netdev ( netdev ) - netdev_rx_unfreeze ( netdev ); -} - -/** - * Release network devices for use via SNP - * - */ -void efi_snp_release ( void ) { - struct net_device *netdev; - - for_each_netdev ( netdev ) - netdev_rx_freeze ( netdev ); + /* Claim SNP devices */ + efi_snp_claimed = claimed; + + /* Update SNP mode state for each interface */ + list_for_each_entry ( snpdev, &efi_snp_devices, list ) + efi_snp_set_state ( snpdev ); }