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