summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-07-20 03:51:53 +0000
committerpeter <peter@FreeBSD.org>2002-07-20 03:51:53 +0000
commit3c805ef8bd61a3ab8eca8e44853ab0eb69df2192 (patch)
treeda8ba722ee4dac361fb771e61064a3098ba09461 /sys
parent4af604d0520417bba59538b8ce875dec93a5e6fb (diff)
downloadFreeBSD-src-3c805ef8bd61a3ab8eca8e44853ab0eb69df2192.zip
FreeBSD-src-3c805ef8bd61a3ab8eca8e44853ab0eb69df2192.tar.gz
Work around some nasty bugs on the [beta] Itanium2's E1000 UNDI driver.
Bug#1: The GetStatus() function returns radically different pointers that do not match any packets we transmitted. I think it might be pointing to a copy of the packet or something. Since we do not transmit more than one packet at a time, just wait for "anything". Bug#2: The Receive() function takes a pointer and a length. However, it either ignores the length or otherwise does bad things and writes outside of ptr[0] through ptr[len-1]. This is bad and causes massive stack corruption for us since we are receiving packets into small buffers on the stack. Instead, Receive() into a large enough buffer and bcopy the data to the requested area.
Diffstat (limited to 'sys')
-rw-r--r--sys/boot/efi/libefi/efinet.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
index 10b1721..f2a6ac4 100644
--- a/sys/boot/efi/libefi/efinet.c
+++ b/sys/boot/efi/libefi/efinet.c
@@ -102,10 +102,14 @@ efinet_put(struct iodesc *desc, void *pkt, size_t len)
return -1;
/* Wait for the buffer to be transmitted */
- buf = 0; /* XXX Is this needed? */
do {
+ buf = 0; /* XXX Is this needed? */
status = net->GetStatus(net, 0, &buf);
- } while (status == EFI_SUCCESS && buf != pkt);
+ /*
+ * XXX EFI1.1 and the E1000 card returns a different
+ * address than we gave. Sigh.
+ */
+ } while (status == EFI_SUCCESS && buf == 0);
/* XXX How do we deal with status != EFI_SUCCESS now? */
return (status == EFI_SUCCESS) ? len : -1;
@@ -120,15 +124,26 @@ efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
EFI_STATUS status;
UINTN bufsz;
time_t t;
+ char buf[2048];
net = nif->nif_devdata;
t = time(0);
while ((time(0) - t) < timeout) {
- bufsz = len;
- status = net->Receive(net, 0, &bufsz, pkt, 0, 0, 0);
- if (status == EFI_SUCCESS)
+ bufsz = sizeof(buf);
+ status = net->Receive(net, 0, &bufsz, buf, 0, 0, 0);
+ if (status == EFI_SUCCESS) {
+ /*
+ * XXX EFI1.1 and the E1000 card trash our
+ * workspace if we do not do this silly copy.
+ * Either they are not respecting the len
+ * value or do not like the alignment.
+ */
+ if (bufsz > len)
+ bufsz = len;
+ bcopy(buf, pkt, bufsz);
return bufsz;
+ }
if (status != EFI_NOT_READY)
return 0;
}
OpenPOWER on IntegriCloud