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

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