Blame SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch

d41074
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
a85e8e
From: Josef Bacik <jbacik@fb.com>
a85e8e
Date: Thu, 6 Aug 2015 10:49:46 -0700
d41074
Subject: [PATCH] efinet: handle get_status() on buggy firmware properly
a85e8e
a85e8e
The EFI spec indicates that get_status() should return the address of the buffer
a85e8e
we passed into transmit to indicate the the buffer was transmitted.  However we
a85e8e
have boxes where the firmware returns some arbitrary address instead, which
a85e8e
makes grub think that we've not sent anything.  So since we have the SNP stuff
a85e8e
opened in exclusive mode just assume any non-NULL txbuf means that our transmit
a85e8e
occurred properly.  This makes grub able to do its networking stuff properly on
a85e8e
our broken firmware.  Thanks,
a85e8e
a85e8e
cc: Peter Jones <pjones@redhat.com>
a85e8e
Signed-off-by: Josef Bacik <jbacik@fb.com>
a85e8e
---
a85e8e
 grub-core/net/drivers/efi/efinet.c | 21 +++++++++++----------
a85e8e
 1 file changed, 11 insertions(+), 10 deletions(-)
a85e8e
a85e8e
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
d41074
index 7b8c4a59d10..ea0e0ca360e 100644
a85e8e
--- a/grub-core/net/drivers/efi/efinet.c
a85e8e
+++ b/grub-core/net/drivers/efi/efinet.c
a85e8e
@@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev,
a85e8e
 	if (st != GRUB_EFI_SUCCESS)
a85e8e
 	  return grub_error (GRUB_ERR_IO,
a85e8e
 			     N_("couldn't send network packet"));
a85e8e
-	if (txbuf == dev->txbuf)
a85e8e
+	/*
a85e8e
+	   Some buggy firmware could return an arbitrary address instead of the
a85e8e
+	   txbuf address we trasmitted, so just check that txbuf is non NULL
a85e8e
+	   for success.  This is ok because we open the SNP protocol in
a85e8e
+	   exclusive mode so we know we're the only ones transmitting on this
a85e8e
+	   box and since we only transmit one packet at a time we know our
a85e8e
+	   transmit was successfull.
a85e8e
+	 */
a85e8e
+	if (txbuf)
a85e8e
 	  {
a85e8e
 	    dev->txbusy = 0;
a85e8e
 	    break;
a85e8e
 	  }
a85e8e
-	if (txbuf)
a85e8e
-	  {
a85e8e
-	    st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size,
a85e8e
-			     dev->txbuf, NULL, NULL, NULL);
a85e8e
-	    if (st != GRUB_EFI_SUCCESS)
a85e8e
-	      return grub_error (GRUB_ERR_IO,
a85e8e
-				 N_("couldn't send network packet"));
a85e8e
-	  }
a85e8e
 	if (limit_time < grub_get_time_ms ())
a85e8e
 	  return grub_error (GRUB_ERR_TIMEOUT,
a85e8e
 			     N_("couldn't send network packet"));
a85e8e
@@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev,
a85e8e
      we run in the GRUB_ERR_TIMEOUT case above.
a85e8e
      Perhaps a timeout in the FW has discarded the recycle buffer.
a85e8e
    */
a85e8e
+  txbuf = NULL;
a85e8e
   st = efi_call_3 (net->get_status, net, 0, &txbuf);
a85e8e
-  dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf);
a85e8e
+  dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf);
a85e8e
 
a85e8e
   return GRUB_ERR_NONE;
a85e8e
 }