diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 5533515fd..70b26af94 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -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); diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index e5dd543a8..1a5e38c1e 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -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);