diff --git a/0001-efinet-Check-for-immediate-completition.patch b/0001-efinet-Check-for-immediate-completition.patch new file mode 100644 index 0000000..988f2a2 --- /dev/null +++ b/0001-efinet-Check-for-immediate-completition.patch @@ -0,0 +1,51 @@ +From cf2b4a36c408084852c44dea045331f039b895d2 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 27 Mar 2015 14:27:56 +0100 +Subject: [PATCH] efinet: Check for immediate completition. + +This both speeds GRUB up and workarounds unexpected EFI behaviour. +--- + grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 2b344d6..f171f20 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -37,11 +37,12 @@ send_card_buffer (struct grub_net_card *dev, + grub_efi_status_t st; + grub_efi_simple_network_t *net = dev->efi_net; + grub_uint64_t limit_time = grub_get_time_ms () + 4000; ++ void *txbuf; + + if (dev->txbusy) + while (1) + { +- void *txbuf = NULL; ++ txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, +@@ -74,7 +75,18 @@ send_card_buffer (struct grub_net_card *dev, + dev->txbuf, NULL, NULL, NULL); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); +- dev->txbusy = 1; ++ ++ /* ++ The card may have sent out the packet immediately - set txbusy ++ to 0 in this case. ++ Cases were observed where checking txbuf at the next call ++ of send_card_buffer() is too late: 0 is returned in txbuf and ++ we run in the GRUB_ERR_TIMEOUT case above. ++ Perhaps a timeout in the FW has discarded the recycle buffer. ++ */ ++ st = efi_call_3 (net->get_status, net, 0, &txbuf); ++ dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf); ++ + return GRUB_ERR_NONE; + } + +-- +2.5.1 + diff --git a/0001-efinet-enable-hardware-filters-when-opening-interfac.patch b/0001-efinet-enable-hardware-filters-when-opening-interfac.patch new file mode 100644 index 0000000..ba0377a --- /dev/null +++ b/0001-efinet-enable-hardware-filters-when-opening-interfac.patch @@ -0,0 +1,107 @@ +From f348aee7b33dd85e7da62b497a96a7319a0bf9dd Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Tue, 16 Jun 2015 19:52:45 +0300 +Subject: [PATCH] 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 +Closes: 45204 +--- + grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++ + include/grub/efi/api.h | 20 +++++++++++++++++--- + 2 files changed, 42 insertions(+), 3 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 5533515..70b26af 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 e5dd543..1a5e38c 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); +-- +2.5.1 + diff --git a/grub2-arm64-efinet-handle-get_status-on-buggy-firmware-properly.patch b/grub2-arm64-efinet-handle-get_status-on-buggy-firmware-properly.patch new file mode 100644 index 0000000..be8ad0b --- /dev/null +++ b/grub2-arm64-efinet-handle-get_status-on-buggy-firmware-properly.patch @@ -0,0 +1,66 @@ +From 4fe8e6d4a1279b1840171d8e797d911cd8443333 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 6 Aug 2015 10:49:46 -0700 +Subject: [PATCH] efinet: handle get_status() on buggy firmware properly + +The EFI spec indicates that get_status() should return the address of the buffer +we passed into transmit to indicate the the buffer was transmitted. However we +have boxes where the firmware returns some arbitrary address instead, which +makes grub think that we've not sent anything. So since we have the SNP stuff +opened in exclusive mode just assume any non-NULL txbuf means that our transmit +occurred properly. This makes grub able to do its networking stuff properly on +our broken firmware. Thanks, + +cc: Peter Jones +Signed-off-by: Josef Bacik +--- + grub-core/net/drivers/efi/efinet.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c +index 70b26af..5388f95 100644 +--- a/grub-core/net/drivers/efi/efinet.c ++++ b/grub-core/net/drivers/efi/efinet.c +@@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev, + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, + N_("couldn't send network packet")); +- if (txbuf == dev->txbuf) ++ /* ++ Some buggy firmware could return an arbitrary address instead of the ++ txbuf address we trasmitted, so just check that txbuf is non NULL ++ for success. This is ok because we open the SNP protocol in ++ exclusive mode so we know we're the only ones transmitting on this ++ box and since we only transmit one packet at a time we know our ++ transmit was successfull. ++ */ ++ if (txbuf) + { + dev->txbusy = 0; + break; + } +- if (txbuf) +- { +- st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size, +- dev->txbuf, NULL, NULL, NULL); +- if (st != GRUB_EFI_SUCCESS) +- return grub_error (GRUB_ERR_IO, +- N_("couldn't send network packet")); +- } + if (limit_time < grub_get_time_ms ()) + return grub_error (GRUB_ERR_TIMEOUT, + N_("couldn't send network packet")); +@@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev, + we run in the GRUB_ERR_TIMEOUT case above. + Perhaps a timeout in the FW has discarded the recycle buffer. + */ ++ txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); +- dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf); ++ dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf); + + return GRUB_ERR_NONE; + } +-- +2.5.1 + diff --git a/grub2.changes b/grub2.changes index bd49c65..087bbc8 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Wed Sep 23 20:02:47 UTC 2015 - dmueller@suse.com + +- add 0001-efinet-Check-for-immediate-completition.patch, + 0001-efinet-enable-hardware-filters-when-opening-interfac.patch, + grub2-arm64-efinet-handle-get_status-on-buggy-firmware-properly.patch + (bsc#947203) + ------------------------------------------------------------------- Mon Sep 14 06:36:04 UTC 2015 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index 4f17179..5686788 100644 --- a/grub2.spec +++ b/grub2.spec @@ -1,7 +1,7 @@ # # spec file for package grub2 # -# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -182,6 +182,8 @@ Patch43: grub2-use-rpmsort-for-version-sorting.patch Patch44: 0001-efidisk-move-device-path-helpers-in-core-for-efinet.patch Patch45: 0002-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch Patch46: 0003-efinet-open-Simple-Network-Protocol-exclusively.patch +Patch47: 0001-efinet-Check-for-immediate-completition.patch +Patch48: 0001-efinet-enable-hardware-filters-when-opening-interfac.patch Patch51: grub2-xen-legacy-config-device-name.patch Patch52: grub2-getroot-support-NVMe-device-names.patch Patch53: grub2-getroot-treat-mdadm-ddf-as-simple-device.patch @@ -250,6 +252,7 @@ Patch237: grub2-ppc64le-fix-64bit-trampoline-in-dyn-linker.patch Patch238: grub2-arm64-Reduce-timer-event-frequency-by-10.patch Patch239: grub2-arm64-set-correct-length.patch Patch240: grub2-arm64-setjmp-Add-missing-license-macro.patch +Patch241: grub2-arm64-efinet-handle-get_status-on-buggy-firmware-properly.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -446,6 +449,8 @@ mv po/grub.pot po/%{name}.pot %patch44 -p1 %patch45 -p1 %patch46 -p1 +%patch47 -p1 +%patch48 -p1 %patch51 -p1 %patch52 -p1 %patch53 -p1 @@ -511,6 +516,7 @@ mv po/grub.pot po/%{name}.pot %patch238 -p1 %patch239 -p1 %patch240 -p1 +%patch241 -p1 # Generate po/LINGUAS for message catalogs ... ./linguas.sh