efinet: enable hardware filters when opening interface
Exclusive open on SNP will close all existing protocol instances which may disable all receive filters on interface. Reinstall them after we opened protocol exclusively. Also follow UEFI specification recommendation and stop interfaces when closing them: Unexpected system errors, reboots and hangs can occur if an OS is loaded and the network devices are not Shutdown() and Stopped(). Also by: Mark Salter <msalter@redhat.com> Closes: 45204
This commit is contained in:
parent
b27af387ea
commit
f348aee7b3
2 changed files with 42 additions and 3 deletions
|
@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev)
|
|||
return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
|
||||
dev->name);
|
||||
|
||||
/* Enable hardware receive filters if driver declares support for it.
|
||||
We need unicast and broadcast and additionaly all nodes and
|
||||
solicited multicast for IPv6. Solicited multicast is per-IPv6
|
||||
address and we currently do not have API to do it so simply
|
||||
try to enable receive of all multicast packets or evertyhing in
|
||||
the worst case (i386 PXE driver always enables promiscuous too).
|
||||
|
||||
This does trust firmware to do what it claims to do.
|
||||
*/
|
||||
if (net->mode->receive_filter_mask)
|
||||
{
|
||||
grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
||||
|
||||
filters &= net->mode->receive_filter_mask;
|
||||
if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
|
||||
filters |= (net->mode->receive_filter_mask &
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
|
||||
|
||||
efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
||||
dev->efi_net, &net_io_guid,
|
||||
grub_efi_image_handle, dev->efi_handle);
|
||||
|
@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev)
|
|||
static void
|
||||
close_card (struct grub_net_card *dev)
|
||||
{
|
||||
efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
|
||||
efi_call_1 (dev->efi_net->stop, dev->efi_net);
|
||||
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
||||
dev->efi_net, &net_io_guid,
|
||||
grub_efi_image_handle, dev->efi_handle);
|
||||
|
|
|
@ -1501,17 +1501,31 @@ enum
|
|||
GRUB_EFI_NETWORK_INITIALIZED,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01,
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02,
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04,
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08,
|
||||
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
|
||||
};
|
||||
|
||||
struct grub_efi_simple_network
|
||||
{
|
||||
grub_uint64_t revision;
|
||||
grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
|
||||
void (*stop) (void);
|
||||
grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
|
||||
grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
|
||||
grub_efi_uintn_t extra_rx,
|
||||
grub_efi_uintn_t extra_tx);
|
||||
void (*reset) (void);
|
||||
void (*shutdown) (void);
|
||||
void (*receive_filters) (void);
|
||||
grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
|
||||
grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
|
||||
grub_uint32_t enable,
|
||||
grub_uint32_t disable,
|
||||
grub_efi_boolean_t reset_mcast_filter,
|
||||
grub_efi_uintn_t mcast_filter_count,
|
||||
grub_efi_mac_address_t *mcast_filter);
|
||||
void (*station_address) (void);
|
||||
void (*statistics) (void);
|
||||
void (*mcastiptomac) (void);
|
||||
|
|
Loading…
Reference in a new issue