|
|
28f7f8 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
ecb9bb |
From: Andrei Borzenkov <arvidjaar@gmail.com>
|
|
|
ecb9bb |
Date: Tue, 16 Jun 2015 19:52:45 +0300
|
|
|
28f7f8 |
Subject: [PATCH] efinet: enable hardware filters when opening interface
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Exclusive open on SNP will close all existing protocol instances which
|
|
|
ecb9bb |
may disable all receive filters on interface. Reinstall them after we
|
|
|
ecb9bb |
opened protocol exclusively.
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Also follow UEFI specification recommendation and stop interfaces when
|
|
|
ecb9bb |
closing them:
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Unexpected system errors, reboots and hangs can occur if an OS is loaded
|
|
|
ecb9bb |
and the network devices are not Shutdown() and Stopped().
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Also by: Mark Salter <msalter@redhat.com>
|
|
|
ecb9bb |
Closes: 45204
|
|
|
ecb9bb |
---
|
|
|
ecb9bb |
grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++
|
|
|
ecb9bb |
include/grub/efi/api.h | 20 +++++++++++++++++---
|
|
|
ecb9bb |
2 files changed, 42 insertions(+), 3 deletions(-)
|
|
|
ecb9bb |
|
|
|
ecb9bb |
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
|
|
|
28f7f8 |
index 6a1dd1f9dff..7b8c4a59d10 100644
|
|
|
ecb9bb |
--- a/grub-core/net/drivers/efi/efinet.c
|
|
|
ecb9bb |
+++ b/grub-core/net/drivers/efi/efinet.c
|
|
|
ecb9bb |
@@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev)
|
|
|
ecb9bb |
return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
|
|
|
ecb9bb |
dev->name);
|
|
|
ecb9bb |
|
|
|
ecb9bb |
+ /* Enable hardware receive filters if driver declares support for it.
|
|
|
ecb9bb |
+ We need unicast and broadcast and additionaly all nodes and
|
|
|
ecb9bb |
+ solicited multicast for IPv6. Solicited multicast is per-IPv6
|
|
|
ecb9bb |
+ address and we currently do not have API to do it so simply
|
|
|
ecb9bb |
+ try to enable receive of all multicast packets or evertyhing in
|
|
|
ecb9bb |
+ the worst case (i386 PXE driver always enables promiscuous too).
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ This does trust firmware to do what it claims to do.
|
|
|
ecb9bb |
+ */
|
|
|
ecb9bb |
+ if (net->mode->receive_filter_mask)
|
|
|
ecb9bb |
+ {
|
|
|
ecb9bb |
+ grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ filters &= net->mode->receive_filter_mask;
|
|
|
ecb9bb |
+ if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
|
|
|
ecb9bb |
+ filters |= (net->mode->receive_filter_mask &
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
|
|
|
ecb9bb |
+ }
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
|
|
ecb9bb |
dev->efi_net, &net_io_guid,
|
|
|
ecb9bb |
grub_efi_image_handle, dev->efi_handle);
|
|
|
ecb9bb |
@@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev)
|
|
|
ecb9bb |
static void
|
|
|
ecb9bb |
close_card (struct grub_net_card *dev)
|
|
|
ecb9bb |
{
|
|
|
ecb9bb |
+ efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
|
|
|
ecb9bb |
+ efi_call_1 (dev->efi_net->stop, dev->efi_net);
|
|
|
ecb9bb |
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
|
|
ecb9bb |
dev->efi_net, &net_io_guid,
|
|
|
ecb9bb |
grub_efi_image_handle, dev->efi_handle);
|
|
|
ecb9bb |
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
|
|
28f7f8 |
index 142340372e1..029ee92f5d0 100644
|
|
|
ecb9bb |
--- a/include/grub/efi/api.h
|
|
|
ecb9bb |
+++ b/include/grub/efi/api.h
|
|
|
ecb9bb |
@@ -1564,17 +1564,31 @@ enum
|
|
|
ecb9bb |
GRUB_EFI_NETWORK_INITIALIZED,
|
|
|
ecb9bb |
};
|
|
|
ecb9bb |
|
|
|
ecb9bb |
+enum
|
|
|
ecb9bb |
+ {
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01,
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02,
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04,
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08,
|
|
|
ecb9bb |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
|
|
|
ecb9bb |
+ };
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
struct grub_efi_simple_network
|
|
|
ecb9bb |
{
|
|
|
ecb9bb |
grub_uint64_t revision;
|
|
|
ecb9bb |
grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
|
|
|
ecb9bb |
- void (*stop) (void);
|
|
|
ecb9bb |
+ grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
|
|
|
ecb9bb |
grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
|
|
|
ecb9bb |
grub_efi_uintn_t extra_rx,
|
|
|
ecb9bb |
grub_efi_uintn_t extra_tx);
|
|
|
ecb9bb |
void (*reset) (void);
|
|
|
ecb9bb |
- void (*shutdown) (void);
|
|
|
ecb9bb |
- void (*receive_filters) (void);
|
|
|
ecb9bb |
+ grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
|
|
|
ecb9bb |
+ grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
|
|
|
ecb9bb |
+ grub_uint32_t enable,
|
|
|
ecb9bb |
+ grub_uint32_t disable,
|
|
|
ecb9bb |
+ grub_efi_boolean_t reset_mcast_filter,
|
|
|
ecb9bb |
+ grub_efi_uintn_t mcast_filter_count,
|
|
|
ecb9bb |
+ grub_efi_mac_address_t *mcast_filter);
|
|
|
ecb9bb |
void (*station_address) (void);
|
|
|
ecb9bb |
void (*statistics) (void);
|
|
|
ecb9bb |
void (*mcastiptomac) (void);
|