Index: bootcd/isolinux/syslinux-6.03/efi/tcp.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/efi/tcp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/efi/tcp.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2013-2014 Intel Corporation - All Rights Reserved
+ */
+
+#include "efi.h"
+#include "net.h"
+#include "fs/pxe/pxe.h"
+
+extern EFI_GUID Tcp4ServiceBindingProtocol;
+extern EFI_GUID Tcp4Protocol;
+
+
+extern struct efi_binding *efi_create_binding(EFI_GUID *, EFI_GUID *);
+extern void efi_destroy_binding(struct efi_binding *, EFI_GUID *);
+int core_tcp_open(struct pxe_pvt_inode *socket)
+{
+    struct efi_binding *b;
+
+    b = efi_create_binding(&Tcp4ServiceBindingProtocol, &Tcp4Protocol);
+    if (!b)
+	return -1;
+
+    socket->net.efi.binding = b;
+
+    return 0;
+}
+
+static EFIAPI void null_cb(EFI_EVENT ev, void *context)
+{
+    EFI_TCP4_COMPLETION_TOKEN *token = context;
+
+    (void)ev;
+
+    uefi_call_wrapper(BS->CloseEvent, 1, token->Event);
+}
+
+static int volatile cb_status = -1;
+static EFIAPI void tcp_cb(EFI_EVENT ev, void *context)
+{
+    EFI_TCP4_COMPLETION_TOKEN *token = context;
+
+    (void)ev;
+
+    if (token->Status == EFI_SUCCESS)
+	cb_status = 0;
+    else
+	cb_status = 1;
+}
+
+int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port)
+{
+    EFI_TCP4_CONNECTION_TOKEN token;
+    EFI_TCP4_ACCESS_POINT *ap;
+    EFI_TCP4_CONFIG_DATA tdata;
+    struct efi_binding *b = socket->net.efi.binding;
+    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;
+    ap->UseDefaultAddress = TRUE;
+    memcpy(&ap->RemoteAddress, &ip, sizeof(ip));
+    ap->RemotePort = port;
+    ap->ActiveFlag = TRUE; /* Initiate active open */
+
+    tdata.TimeToLive = 64;
+
+    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;
+
+    status = efi_setup_event(&token.CompletionToken.Event,
+			    (EFI_EVENT_NOTIFY)tcp_cb, &token.CompletionToken);
+    if (status != EFI_SUCCESS)
+	return -1;
+
+    status = uefi_call_wrapper(tcp->Connect, 2, tcp, &token);
+    if (status != EFI_SUCCESS) {
+	Print(L"Failed to connect: %d\n", status);
+	goto out;
+    }
+
+    while (cb_status == -1)
+	uefi_call_wrapper(tcp->Poll, 1, tcp);
+
+    if (cb_status == 0)
+	rv = 0;
+
+    /* Reset */
+    cb_status = -1;
+
+out:
+    uefi_call_wrapper(BS->CloseEvent, 1, token.CompletionToken.Event);
+    return rv;
+}
+
+bool core_tcp_is_connected(struct pxe_pvt_inode *socket)
+{
+    if (socket->net.efi.binding)
+	return true;
+
+    return false;
+}
+
+int core_tcp_write(struct pxe_pvt_inode *socket, const void *data,
+		   size_t len, bool copy)
+{
+    EFI_TCP4_TRANSMIT_DATA txdata;
+    EFI_TCP4_FRAGMENT_DATA *frag;
+    struct efi_binding *b = socket->net.efi.binding;
+    EFI_TCP4_IO_TOKEN iotoken;
+    EFI_STATUS status;
+    EFI_TCP4 *tcp = (EFI_TCP4 *)b->this;
+    int rv = -1;
+
+    (void)copy;
+
+    memset(&iotoken, 0, sizeof(iotoken));
+    memset(&txdata, 0, sizeof(txdata));
+
+    txdata.DataLength = len;
+    txdata.FragmentCount = 1;
+
+    frag = &txdata.FragmentTable[0];
+    frag->FragmentLength = len;
+    frag->FragmentBuffer = (void *)data;
+
+    iotoken.Packet.TxData = &txdata;
+
+    status = efi_setup_event(&iotoken.CompletionToken.Event,
+			     (EFI_EVENT_NOTIFY)tcp_cb, &iotoken.CompletionToken);
+    if (status != EFI_SUCCESS)
+	return -1;
+
+    status = uefi_call_wrapper(tcp->Transmit, 2, tcp, &iotoken);
+    if (status != EFI_SUCCESS) {
+	Print(L"tcp transmit failed, %d\n", status);
+	goto out;
+    }
+
+    while (cb_status == -1)
+	uefi_call_wrapper(tcp->Poll, 1, tcp);
+
+    if (cb_status == 0)
+	rv = 0;
+
+    /* Reset */
+    cb_status = -1;
+
+out:
+    uefi_call_wrapper(BS->CloseEvent, 1, iotoken.CompletionToken.Event);
+    return rv;
+}
+
+void core_tcp_close_file(struct inode *inode)
+{
+    struct pxe_pvt_inode *socket = PVT(inode);
+    struct efi_binding *b = socket->net.efi.binding;
+    EFI_TCP4_CLOSE_TOKEN token;
+    EFI_STATUS status;
+    EFI_TCP4 *tcp = (EFI_TCP4 *)b->this;
+
+  if (!socket->tftp_goteof) {
+	memset(&token, 0, sizeof(token));
+
+	status = efi_setup_event(&token.CompletionToken.Event,
+				 (EFI_EVENT_NOTIFY)null_cb,
+				 &token.CompletionToken);
+	if (status != EFI_SUCCESS)
+	    return;
+
+	status = uefi_call_wrapper(tcp->Close, 2, tcp, &token);
+	if (status != EFI_SUCCESS)
+	    Print(L"tcp close failed: %d\n", status);
+    }
+
+    efi_destroy_binding(b, &Tcp4ServiceBindingProtocol);
+    socket->net.efi.binding = NULL;
+}
+
+static char databuf[8192];
+
+void core_tcp_fill_buffer(struct inode *inode)
+{
+    struct pxe_pvt_inode *socket = PVT(inode);
+    struct efi_binding *b = socket->net.efi.binding;
+    EFI_TCP4_IO_TOKEN iotoken;
+    EFI_TCP4_RECEIVE_DATA rxdata;
+    EFI_TCP4_FRAGMENT_DATA *frag;
+    EFI_STATUS status;
+    EFI_TCP4 *tcp = (EFI_TCP4 *)b->this;
+    void *data;
+    size_t len;
+
+    memset(&iotoken, 0, sizeof(iotoken));
+    memset(&rxdata, 0, sizeof(rxdata));
+
+    status = efi_setup_event(&iotoken.CompletionToken.Event,
+		      (EFI_EVENT_NOTIFY)tcp_cb, &iotoken.CompletionToken);
+    if (status != EFI_SUCCESS)
+	return;
+
+    iotoken.Packet.RxData = &rxdata;
+    rxdata.FragmentCount = 1;
+    rxdata.DataLength = sizeof(databuf);
+    frag = &rxdata.FragmentTable[0];
+    frag->FragmentBuffer = databuf;
+    frag->FragmentLength = sizeof(databuf);
+
+    status = uefi_call_wrapper(tcp->Receive, 2, tcp, &iotoken);
+    if (status == EFI_CONNECTION_FIN) {
+	socket->tftp_goteof = 1;
+	if (inode->size == (uint64_t)-1)
+	    inode->size = socket->tftp_filepos;
+	socket->ops->close(inode);
+	goto out;
+    }
+
+    while (cb_status == -1)
+	uefi_call_wrapper(tcp->Poll, 1, tcp);
+
+    /* Reset */
+    cb_status = -1;
+
+    len = frag->FragmentLength;
+    memcpy(databuf, frag->FragmentBuffer, len);
+    data = databuf;
+
+    socket->tftp_dataptr = data;
+    socket->tftp_filepos += len;
+    socket->tftp_bytesleft = len;
+
+out:
+    uefi_call_wrapper(BS->CloseEvent, 1, iotoken.CompletionToken.Event);
+}
