aboutsummaryrefslogtreecommitdiffstats
path: root/efi
diff options
context:
space:
mode:
Diffstat (limited to 'efi')
-rw-r--r--efi/efi.h5
-rw-r--r--efi/tcp.c22
-rw-r--r--efi/udp.c85
3 files changed, 81 insertions, 31 deletions
diff --git a/efi/efi.h b/efi/efi.h
index 9e4a4432..ef5bacb3 100644
--- a/efi/efi.h
+++ b/efi/efi.h
@@ -24,6 +24,11 @@
#include <efilib.h>
#include <efistdarg.h>
+/* Delay for 100 ms */
+#define EFI_NOMAP_PRINT_DELAY 100
+/* We should keep EFI_NOMAP_PRINT_COUNT at 10 to limit flooding the console */
+#define EFI_NOMAP_PRINT_COUNT 10
+
struct efi_disk_private {
EFI_HANDLE dev_handle;
EFI_BLOCK_IO *bio;
diff --git a/efi/tcp.c b/efi/tcp.c
index 1b9b93f2..b90efaf3 100644
--- a/efi/tcp.c
+++ b/efi/tcp.c
@@ -56,19 +56,35 @@ int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port)
EFI_STATUS status;
EFI_TCP4 *tcp = (EFI_TCP4 *)b->this;
int rv = -1;
+ int unmapped = 1;
+ jiffies_t start, last, cur;
memset(&tdata, 0, sizeof(tdata));
ap = &tdata.AccessPoint;
- memcpy(&ap->StationAddress, &IPInfo.myip, sizeof(IPInfo.myip));
- memcpy(&ap->SubnetMask, &IPInfo.netmask, sizeof(IPInfo.netmask));
+ ap->UseDefaultAddress = TRUE;
memcpy(&ap->RemoteAddress, &ip, sizeof(ip));
ap->RemotePort = port;
ap->ActiveFlag = TRUE; /* Initiate active open */
tdata.TimeToLive = 64;
- status = uefi_call_wrapper(tcp->Configure, 2, tcp, &tdata);
+ last = start = jiffies();
+ while (unmapped){
+ status = uefi_call_wrapper(tcp->Configure, 2, tcp, &tdata);
+ if (status != EFI_NO_MAPPING)
+ unmapped = 0;
+ else {
+ cur = jiffies();
+ if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) {
+ last = cur;
+ Print(L"core_tcp_connect: stalling on configure with no mapping\n");
+ } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) {
+ Print(L"core_tcp_connect: aborting on no mapping\n");
+ unmapped = 0;
+ }
+ }
+ }
if (status != EFI_SUCCESS)
return -1;
diff --git a/efi/udp.c b/efi/udp.c
index 80cad868..7c1d09e2 100644
--- a/efi/udp.c
+++ b/efi/udp.c
@@ -18,6 +18,42 @@ extern EFI_GUID Udp4ServiceBindingProtocol, Udp4Protocol;
*/
static struct efi_binding *udp_reader;
+/**
+ * Try to configure this UDP socket
+ *
+ * @param:udp, the EFI_UDP4 socket to configure
+ * @param:udata, the EFI_UDP4_CONFIG_DATA to use
+ * @param:f, the name of the function as a wide string.
+ *
+ * @out: status as EFI_STATUS
+ */
+
+EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata,
+ short unsigned int *f)
+{
+ EFI_STATUS status;
+ int unmapped = 1;
+ jiffies_t start, last, cur;
+
+ last = start = jiffies();
+ while (unmapped){
+ status = uefi_call_wrapper(udp->Configure, 2, udp, udata);
+ if (status != EFI_NO_MAPPING)
+ unmapped = 0;
+ else {
+ cur = jiffies();
+ if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) {
+ last = cur;
+ Print(L"%s: stalling on configure with no mapping\n", f);
+ } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) {
+ Print(L"%s: aborting on no mapping\n", f);
+ unmapped = 0;
+ }
+ }
+ }
+ return status;
+}
+
/**
* Open a socket
*
@@ -45,15 +81,25 @@ int core_udp_open(struct pxe_pvt_inode *socket)
udp = (EFI_UDP4 *)udp_reader->this;
memset(&udata, 0, sizeof(udata));
- udata.AcceptPromiscuous = TRUE;
- udata.AcceptAnyPort = TRUE;
- status = uefi_call_wrapper(udp->Configure, 2, udp, &udata);
+ status = core_udp_configure(udp, &udata, L"core_udp_open");
if (status != EFI_SUCCESS)
goto bail;
socket->net.efi.binding = b;
+ /*
+ * Save the random local port number that the UDPv4 Protocol
+ * Driver picked for us. The TFTP protocol uses the local port
+ * number as the TID.
+ */
+ status = uefi_call_wrapper(udp->GetModeData, 5, udp,
+ &udata, NULL, NULL, NULL);
+ if (status != EFI_SUCCESS)
+ Print(L"Failed to get UDP mode data: %d\n", status);
+ else
+ socket->net.efi.localport = udata.StationPort;
+
return 0;
bail:
@@ -104,33 +150,17 @@ void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip,
/* Re-use the existing local port number */
udata.StationPort = socket->net.efi.localport;
- memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip));
- memcpy(&udata.SubnetMask, &IPInfo.netmask, sizeof(IPInfo.netmask));
+ udata.UseDefaultAddress = TRUE;
memcpy(&udata.RemoteAddress, &ip, sizeof(ip));
udata.RemotePort = port;
udata.AcceptPromiscuous = TRUE;
udata.TimeToLive = 64;
- status = uefi_call_wrapper(udp->Configure, 2, udp, &udata);
+ status = core_udp_configure(udp, &udata, L"core_udp_connect");
if (status != EFI_SUCCESS) {
Print(L"Failed to configure UDP: %d\n", status);
return;
}
-
- /*
- * If this is the first time connecting, save the random local port
- * number that the UDPv4 Protocol Driver picked for us. The TFTP
- * protocol uses the local port number as the TID, and it needs to
- * be consistent across connect()/disconnect() calls.
- */
- if (!socket->net.efi.localport) {
- status = uefi_call_wrapper(udp->GetModeData, 5, udp,
- &udata, NULL, NULL, NULL);
- if (status != EFI_SUCCESS)
- Print(L"Failed to get UDP mode data: %d\n", status);
- else
- socket->net.efi.localport = udata.StationPort;
- }
}
/**
@@ -192,6 +222,7 @@ int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
b = udp_reader;
udp = (EFI_UDP4 *)b->this;
+ memset(&token, 0, sizeof(token));
status = efi_setup_event(&token.Event, (EFI_EVENT_NOTIFY)udp4_cb,
&token);
@@ -273,8 +304,6 @@ void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
if (status != EFI_SUCCESS)
goto bail;
- txdata->UdpSessionData = NULL;
- txdata->GatewayAddress = NULL;
txdata->DataLength = len;
txdata->FragmentCount = 1;
frag = &txdata->FragmentTable[0];
@@ -340,14 +369,16 @@ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data,
memset(&udata, 0, sizeof(udata));
- memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip));
- memcpy(&udata.SubnetMask, &IPInfo.netmask, sizeof(IPInfo.netmask));
+ /* Re-use the existing local port number */
+ udata.StationPort = socket->net.efi.localport;
+
+ udata.UseDefaultAddress = TRUE;
memcpy(&udata.RemoteAddress, &ip, sizeof(ip));
udata.RemotePort = port;
udata.AcceptPromiscuous = TRUE;
udata.TimeToLive = 64;
- status = uefi_call_wrapper(udp->Configure, 2, udp, &udata);
+ status = core_udp_configure(udp, &udata, L"core_udp_sendto");
if (status != EFI_SUCCESS)
goto bail;
@@ -356,8 +387,6 @@ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data,
if (status != EFI_SUCCESS)
goto bail;
- txdata->UdpSessionData = NULL;
- txdata->GatewayAddress = NULL;
txdata->DataLength = len;
txdata->FragmentCount = 1;
frag = &txdata->FragmentTable[0];