Blame SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch

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