176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2013-2014 Intel Corporation - All Rights Reserved 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "efi.h" 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "net.h" 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "fs/pxe/pxe.h" 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern EFI_GUID Tcp4ServiceBindingProtocol; 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern EFI_GUID Tcp4Protocol; 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern struct efi_binding *efi_create_binding(EFI_GUID *, EFI_GUID *); 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void efi_destroy_binding(struct efi_binding *, EFI_GUID *); 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint core_tcp_open(struct pxe_pvt_inode *socket) 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct efi_binding *b; 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman b = efi_create_binding(&Tcp4ServiceBindingProtocol, &Tcp4Protocol); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!b) 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->net.efi.binding = b; 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic EFIAPI void null_cb(EFI_EVENT ev, void *context) 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_COMPLETION_TOKEN *token = context; 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)ev; 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(BS->CloseEvent, 1, token->Event); 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int volatile cb_status = -1; 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic EFIAPI void tcp_cb(EFI_EVENT ev, void *context) 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_COMPLETION_TOKEN *token = context; 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)ev; 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (token->Status == EFI_SUCCESS) 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cb_status = 0; 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cb_status = 1; 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port) 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_CONNECTION_TOKEN token; 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_ACCESS_POINT *ap; 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_CONFIG_DATA tdata; 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct efi_binding *b = socket->net.efi.binding; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_STATUS status; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4 *tcp = (EFI_TCP4 *)b->this; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rv = -1; 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int unmapped = 1; 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman jiffies_t start, last, cur; 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&tdata, 0, sizeof(tdata)); 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ap = &tdata.AccessPoint; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ap->UseDefaultAddress = TRUE; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(&ap->RemoteAddress, &ip, sizeof(ip)); 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ap->RemotePort = port; 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ap->ActiveFlag = TRUE; /* Initiate active open */ 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tdata.TimeToLive = 64; 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman last = start = jiffies(); 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (unmapped){ 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = uefi_call_wrapper(tcp->Configure, 2, tcp, &tdata); 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_NO_MAPPING) 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unmapped = 0; 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cur = jiffies(); 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) { 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman last = cur; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Print(L"core_tcp_connect: stalling on configure with no mapping\n"); 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) { 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Print(L"core_tcp_connect: aborting on no mapping\n"); 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unmapped = 0; 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = efi_setup_event(&token.CompletionToken.Event, 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (EFI_EVENT_NOTIFY)tcp_cb, &token.CompletionToken); 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = uefi_call_wrapper(tcp->Connect, 2, tcp, &token); 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) { 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Print(L"Failed to connect: %d\n", status); 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto out; 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (cb_status == -1) 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(tcp->Poll, 1, tcp); 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cb_status == 0) 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = 0; 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Reset */ 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cb_status = -1; 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanout: 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(BS->CloseEvent, 1, token.CompletionToken.Event); 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv; 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbool core_tcp_is_connected(struct pxe_pvt_inode *socket) 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (socket->net.efi.binding) 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return true; 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return false; 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint core_tcp_write(struct pxe_pvt_inode *socket, const void *data, 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t len, bool copy) 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_TRANSMIT_DATA txdata; 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_FRAGMENT_DATA *frag; 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct efi_binding *b = socket->net.efi.binding; 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_IO_TOKEN iotoken; 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_STATUS status; 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4 *tcp = (EFI_TCP4 *)b->this; 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rv = -1; 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)copy; 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&iotoken, 0, sizeof(iotoken)); 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&txdata, 0, sizeof(txdata)); 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txdata.DataLength = len; 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txdata.FragmentCount = 1; 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag = &txdata.FragmentTable[0]; 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag->FragmentLength = len; 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag->FragmentBuffer = (void *)data; 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iotoken.Packet.TxData = &txdata; 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = efi_setup_event(&iotoken.CompletionToken.Event, 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (EFI_EVENT_NOTIFY)tcp_cb, &iotoken.CompletionToken); 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = uefi_call_wrapper(tcp->Transmit, 2, tcp, &iotoken); 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) { 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Print(L"tcp transmit failed, %d\n", status); 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto out; 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (cb_status == -1) 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(tcp->Poll, 1, tcp); 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cb_status == 0) 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = 0; 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Reset */ 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cb_status = -1; 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanout: 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(BS->CloseEvent, 1, iotoken.CompletionToken.Event); 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv; 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid core_tcp_close_file(struct inode *inode) 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct pxe_pvt_inode *socket = PVT(inode); 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct efi_binding *b = socket->net.efi.binding; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_CLOSE_TOKEN token; 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_STATUS status; 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4 *tcp = (EFI_TCP4 *)b->this; 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!socket->tftp_goteof) { 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&token, 0, sizeof(token)); 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = efi_setup_event(&token.CompletionToken.Event, 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (EFI_EVENT_NOTIFY)null_cb, 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &token.CompletionToken); 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = uefi_call_wrapper(tcp->Close, 2, tcp, &token); 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Print(L"tcp close failed: %d\n", status); 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman efi_destroy_binding(b, &Tcp4ServiceBindingProtocol); 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->net.efi.binding = NULL; 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic char databuf[8192]; 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid core_tcp_fill_buffer(struct inode *inode) 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct pxe_pvt_inode *socket = PVT(inode); 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct efi_binding *b = socket->net.efi.binding; 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_IO_TOKEN iotoken; 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_RECEIVE_DATA rxdata; 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4_FRAGMENT_DATA *frag; 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_STATUS status; 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EFI_TCP4 *tcp = (EFI_TCP4 *)b->this; 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void *data; 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t len; 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&iotoken, 0, sizeof(iotoken)); 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&rxdata, 0, sizeof(rxdata)); 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = efi_setup_event(&iotoken.CompletionToken.Event, 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (EFI_EVENT_NOTIFY)tcp_cb, &iotoken.CompletionToken); 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status != EFI_SUCCESS) 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iotoken.Packet.RxData = &rxdata; 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxdata.FragmentCount = 1; 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxdata.DataLength = sizeof(databuf); 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag = &rxdata.FragmentTable[0]; 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag->FragmentBuffer = databuf; 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman frag->FragmentLength = sizeof(databuf); 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = uefi_call_wrapper(tcp->Receive, 2, tcp, &iotoken); 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status == EFI_CONNECTION_FIN) { 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->tftp_goteof = 1; 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (inode->size == (uint64_t)-1) 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman inode->size = socket->tftp_filepos; 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->ops->close(inode); 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto out; 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (cb_status == -1) 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(tcp->Poll, 1, tcp); 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Reset */ 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cb_status = -1; 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = frag->FragmentLength; 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(databuf, frag->FragmentBuffer, len); 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman data = databuf; 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->tftp_dataptr = data; 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->tftp_filepos += len; 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman socket->tftp_bytesleft = len; 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanout: 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uefi_call_wrapper(BS->CloseEvent, 1, iotoken.CompletionToken.Event); 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 255