mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 11:29:11 +00:00 
			
		
		
		
	change Some unexpected error happened. to Other errors as indicated. 2) delete unused parameter in IScsiConfigFormInit() 3) correct IN OUT mistake in IScsiSessionInit () 4)roll back one update for Piece of code in IScsiDhcp.c around line 99 on FieldIndex git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7013 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			488 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			488 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The wrap of TCP/IP Socket interface.
 | 
						|
 | 
						|
Copyright (c) 2004 - 2007, Intel Corporation.<BR>
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "IScsiImpl.h"
 | 
						|
 | 
						|
/**
 | 
						|
  The common notify function associated with various Tcp4Io events. 
 | 
						|
 | 
						|
  @param[in]  Event   The event signaled.
 | 
						|
  @param[in]  Context The context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Tcp4IoCommonNotify (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  *((BOOLEAN *) Context) = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a TCP socket with the specified configuration data. 
 | 
						|
 | 
						|
  @param[in]  Image      The handle of the driver image.
 | 
						|
  @param[in]  Controller The handle of the controller.
 | 
						|
  @param[in]  ConfigData The Tcp4 configuration data.
 | 
						|
  @param[in]  Tcp4Io     The Tcp4Io.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS    The TCP socket is created and configured.
 | 
						|
  @retval Others         Failed to create the TCP socket or configure it.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Tcp4IoCreateSocket (
 | 
						|
  IN EFI_HANDLE           Image,
 | 
						|
  IN EFI_HANDLE           Controller,
 | 
						|
  IN TCP4_IO_CONFIG_DATA  *ConfigData,
 | 
						|
  IN TCP4_IO              *Tcp4Io
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_TCP4_PROTOCOL     *Tcp4;
 | 
						|
  EFI_TCP4_CONFIG_DATA  Tcp4ConfigData;
 | 
						|
  EFI_TCP4_OPTION       ControlOption;
 | 
						|
  EFI_TCP4_ACCESS_POINT *AccessPoint;
 | 
						|
 | 
						|
  Tcp4Io->Handle = NULL;
 | 
						|
  Tcp4Io->ConnToken.CompletionToken.Event = NULL;
 | 
						|
  Tcp4Io->TxToken.CompletionToken.Event = NULL;
 | 
						|
  Tcp4Io->RxToken.CompletionToken.Event = NULL;
 | 
						|
  Tcp4Io->CloseToken.CompletionToken.Event = NULL;
 | 
						|
  Tcp4 = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the TCP4 child instance and get the TCP4 protocol.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
            Controller,
 | 
						|
            Image,
 | 
						|
            &gEfiTcp4ServiceBindingProtocolGuid,
 | 
						|
            &Tcp4Io->Handle
 | 
						|
            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Tcp4Io->Handle,
 | 
						|
                  &gEfiTcp4ProtocolGuid,
 | 
						|
                  (VOID **)&Tcp4Io->Tcp4,
 | 
						|
                  Image,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Tcp4Io->Image       = Image;
 | 
						|
  Tcp4Io->Controller  = Controller;
 | 
						|
  Tcp4                = Tcp4Io->Tcp4;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the configuration parameters.
 | 
						|
  //
 | 
						|
  ControlOption.ReceiveBufferSize       = 0x200000;
 | 
						|
  ControlOption.SendBufferSize          = 0x200000;
 | 
						|
  ControlOption.MaxSynBackLog           = 0;
 | 
						|
  ControlOption.ConnectionTimeout       = 0;
 | 
						|
  ControlOption.DataRetries             = 6;
 | 
						|
  ControlOption.FinTimeout              = 0;
 | 
						|
  ControlOption.TimeWaitTimeout         = 0;
 | 
						|
  ControlOption.KeepAliveProbes         = 4;
 | 
						|
  ControlOption.KeepAliveTime           = 0;
 | 
						|
  ControlOption.KeepAliveInterval       = 0;
 | 
						|
  ControlOption.EnableNagle             = FALSE;
 | 
						|
  ControlOption.EnableTimeStamp         = FALSE;
 | 
						|
  ControlOption.EnableWindowScaling     = TRUE;
 | 
						|
  ControlOption.EnableSelectiveAck      = FALSE;
 | 
						|
  ControlOption.EnablePathMtuDiscovery  = FALSE;
 | 
						|
 | 
						|
  Tcp4ConfigData.TypeOfService          = 8;
 | 
						|
  Tcp4ConfigData.TimeToLive             = 255;
 | 
						|
  Tcp4ConfigData.ControlOption          = &ControlOption;
 | 
						|
 | 
						|
  AccessPoint = &Tcp4ConfigData.AccessPoint;
 | 
						|
 | 
						|
  AccessPoint->UseDefaultAddress = FALSE;
 | 
						|
  AccessPoint->StationPort = 0;
 | 
						|
  AccessPoint->RemotePort = ConfigData->RemotePort;
 | 
						|
  AccessPoint->ActiveFlag = TRUE;
 | 
						|
 | 
						|
  CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
  //
 | 
						|
  // Configure the TCP4 protocol.
 | 
						|
  //
 | 
						|
  Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {
 | 
						|
    //
 | 
						|
    // the gateway is not zero, add the default route by hand
 | 
						|
    //
 | 
						|
    Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Create events for variuos asynchronous operations.
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Tcp4IoCommonNotify,
 | 
						|
                  &Tcp4Io->IsConnDone,
 | 
						|
                  &Tcp4Io->ConnToken.CompletionToken.Event
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Tcp4IoCommonNotify,
 | 
						|
                  &Tcp4Io->IsTxDone,
 | 
						|
                  &Tcp4Io->TxToken.CompletionToken.Event
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Tcp4IoCommonNotify,
 | 
						|
                  &Tcp4Io->IsRxDone,
 | 
						|
                  &Tcp4Io->RxToken.CompletionToken.Event
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  Tcp4IoCommonNotify,
 | 
						|
                  &Tcp4Io->IsCloseDone,
 | 
						|
                  &Tcp4Io->CloseToken.CompletionToken.Event
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Tcp4Io->IsTxDone  = FALSE;
 | 
						|
  Tcp4Io->IsRxDone  = FALSE;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
 | 
						|
  if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {
 | 
						|
    gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {
 | 
						|
    gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {
 | 
						|
    gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Tcp4 != NULL) {
 | 
						|
    Tcp4->Configure (Tcp4, NULL);
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Tcp4Io->Handle,
 | 
						|
          &gEfiTcp4ProtocolGuid,
 | 
						|
          Image,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
  }
 | 
						|
 | 
						|
  NetLibDestroyServiceChild (
 | 
						|
    Controller,
 | 
						|
    Image,
 | 
						|
    &gEfiTcp4ServiceBindingProtocolGuid,
 | 
						|
    Tcp4Io->Handle
 | 
						|
    );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy the socket. 
 | 
						|
 | 
						|
  @param[in]  Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Tcp4IoDestroySocket (
 | 
						|
  IN TCP4_IO  *Tcp4Io
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_TCP4_PROTOCOL *Tcp4;
 | 
						|
 | 
						|
  Tcp4 = Tcp4Io->Tcp4;
 | 
						|
 | 
						|
  Tcp4->Configure (Tcp4, NULL);
 | 
						|
 | 
						|
  gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
 | 
						|
  gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
 | 
						|
  gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Tcp4Io->Handle,
 | 
						|
        &gEfiTcp4ProtocolGuid,
 | 
						|
        Tcp4Io->Image,
 | 
						|
        Tcp4Io->Controller
 | 
						|
        );
 | 
						|
 | 
						|
  NetLibDestroyServiceChild (
 | 
						|
    Tcp4Io->Controller,
 | 
						|
    Tcp4Io->Image,
 | 
						|
    &gEfiTcp4ServiceBindingProtocolGuid,
 | 
						|
    Tcp4Io->Handle
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Connect to the other endpoint of the TCP socket.
 | 
						|
 | 
						|
  @param[in]  Tcp4Io  The Tcp4Io wrapping the TCP socket.
 | 
						|
  @param[in]  Timeout The time to wait for connection done.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS          Connect to the other endpoint of the TCP socket successfully.
 | 
						|
  @retval EFI_TIMEOUT          Failed to connect to the other endpoint of the TCP socket in the                               specified time period.
 | 
						|
  @retval Others               Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Tcp4IoConnect (
 | 
						|
  IN TCP4_IO    *Tcp4Io,
 | 
						|
  IN EFI_EVENT  Timeout
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_TCP4_PROTOCOL *Tcp4;
 | 
						|
  EFI_STATUS        Status;
 | 
						|
 | 
						|
  Tcp4Io->IsConnDone  = FALSE;
 | 
						|
  Tcp4                = Tcp4Io->Tcp4;
 | 
						|
  Status              = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {
 | 
						|
    Tcp4->Poll (Tcp4);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Tcp4Io->IsConnDone) {
 | 
						|
    Status = EFI_TIMEOUT;
 | 
						|
  } else {
 | 
						|
    Status = Tcp4Io->ConnToken.CompletionToken.Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Reset the socket.
 | 
						|
 | 
						|
  @param[in]  Tcp4Io The Tcp4Io wrapping the TCP socket.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Tcp4IoReset (
 | 
						|
  IN TCP4_IO  *Tcp4Io
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  EFI_TCP4_PROTOCOL *Tcp4;
 | 
						|
 | 
						|
  Tcp4Io->CloseToken.AbortOnClose = TRUE;
 | 
						|
  Tcp4Io->IsCloseDone             = FALSE;
 | 
						|
 | 
						|
  Tcp4 = Tcp4Io->Tcp4;
 | 
						|
  Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  while (!Tcp4Io->IsCloseDone) {
 | 
						|
    Tcp4->Poll (Tcp4);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Transmit the Packet to the other endpoint of the socket.
 | 
						|
 | 
						|
  @param[in]   Tcp4Io          The Tcp4Io wrapping the TCP socket.
 | 
						|
  @param[in]   Packet          The packet to transmit.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS          The packet is trasmitted.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
 | 
						|
  @retval Others               Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Tcp4IoTransmit (
 | 
						|
  IN TCP4_IO  *Tcp4Io,
 | 
						|
  IN NET_BUF  *Packet
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_TCP4_TRANSMIT_DATA  *TxData;
 | 
						|
  EFI_TCP4_PROTOCOL       *Tcp4;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
 | 
						|
  TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));
 | 
						|
  if (TxData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  TxData->Push        = TRUE;
 | 
						|
  TxData->Urgent      = FALSE;
 | 
						|
  TxData->DataLength  = Packet->TotalSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Build the fragment table.
 | 
						|
  //
 | 
						|
  TxData->FragmentCount = Packet->BlockOpNum;
 | 
						|
  NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);
 | 
						|
 | 
						|
  Tcp4Io->TxToken.Packet.TxData = TxData;
 | 
						|
 | 
						|
  //
 | 
						|
  // Trasnmit the packet.
 | 
						|
  //
 | 
						|
  Tcp4    = Tcp4Io->Tcp4;
 | 
						|
  Status  = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  while (!Tcp4Io->IsTxDone) {
 | 
						|
    Tcp4->Poll (Tcp4);
 | 
						|
  }
 | 
						|
 | 
						|
  Tcp4Io->IsTxDone  = FALSE;
 | 
						|
 | 
						|
  Status            = Tcp4Io->TxToken.CompletionToken.Status;
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
 | 
						|
  gBS->FreePool (TxData);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receive data from the socket.
 | 
						|
 | 
						|
  @param[in]  Tcp4Io           The Tcp4Io which wraps the socket to be destroyed.
 | 
						|
  @param[in]  Packet           The buffer to hold the data copy from the soket rx buffer.
 | 
						|
  @param[in]  AsyncMode        Is this receive asyncronous or not.
 | 
						|
  @param[in]  Timeout          The time to wait for receiving the amount of data the Packet
 | 
						|
                               can hold.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          The required amount of data is received from the socket.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.
 | 
						|
  @retval EFI_TIMEOUT          Failed to receive the required amount of data in the
 | 
						|
                               specified time period.
 | 
						|
  @retval Others               Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Tcp4IoReceive (
 | 
						|
  IN TCP4_IO    *Tcp4Io,
 | 
						|
  IN NET_BUF    *Packet,
 | 
						|
  IN BOOLEAN    AsyncMode,
 | 
						|
  IN EFI_EVENT  Timeout
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_TCP4_PROTOCOL     *Tcp4;
 | 
						|
  EFI_TCP4_RECEIVE_DATA RxData;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  NET_FRAGMENT          *Fragment;
 | 
						|
  UINT32                FragmentCount;
 | 
						|
  UINT32                CurrentFragment;
 | 
						|
 | 
						|
  FragmentCount = Packet->BlockOpNum;
 | 
						|
  Fragment      = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
 | 
						|
  if (Fragment == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Build the fragment table.
 | 
						|
  //
 | 
						|
  NetbufBuildExt (Packet, Fragment, &FragmentCount);
 | 
						|
 | 
						|
  RxData.FragmentCount          = 1;
 | 
						|
  Tcp4Io->RxToken.Packet.RxData = &RxData;
 | 
						|
  CurrentFragment               = 0;
 | 
						|
  Tcp4                          = Tcp4Io->Tcp4;
 | 
						|
  Status                        = EFI_SUCCESS;
 | 
						|
 | 
						|
  while (CurrentFragment < FragmentCount) {
 | 
						|
    RxData.DataLength                       = Fragment[CurrentFragment].Len;
 | 
						|
    RxData.FragmentTable[0].FragmentLength  = Fragment[CurrentFragment].Len;
 | 
						|
    RxData.FragmentTable[0].FragmentBuffer  = Fragment[CurrentFragment].Bulk;
 | 
						|
 | 
						|
    Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
 | 
						|
    while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
 | 
						|
      //
 | 
						|
      // Poll until some data is received or something error happens.
 | 
						|
      //
 | 
						|
      Tcp4->Poll (Tcp4);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!Tcp4Io->IsRxDone) {
 | 
						|
      //
 | 
						|
      // Timeout occurs, cancel the receive request.
 | 
						|
      //
 | 
						|
      Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);
 | 
						|
 | 
						|
      Status = EFI_TIMEOUT;
 | 
						|
      goto ON_EXIT;
 | 
						|
    } else {
 | 
						|
      Tcp4Io->IsRxDone = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {
 | 
						|
      Status = Tcp4Io->RxToken.CompletionToken.Status;
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
 | 
						|
    Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;
 | 
						|
    if (Fragment[CurrentFragment].Len == 0) {
 | 
						|
      CurrentFragment++;
 | 
						|
    } else {
 | 
						|
      Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
 | 
						|
  gBS->FreePool (Fragment);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |