Exemple #1
0
/**
  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:

  FreePool (TxData);

  return Status;
}
Exemple #2
0
/**
  Receive the Packet by processing the associated HTTPS token.

  @param[in, out]   HttpInstance    Pointer to HTTP_PROTOCOL structure.
  @param[in]        Packet          The packet to transmit.
  @param[in]        Timeout         The time to wait for connection done.

  @retval EFI_SUCCESS            The Packet is received.
  @retval EFI_INVALID_PARAMETER  HttpInstance is NULL or Packet is NULL.
  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resources.
  @retval EFI_TIMEOUT            The operation is time out.
  @retval Others                 Other error as indicated.

**/
EFI_STATUS
EFIAPI
TlsCommonReceive (
  IN OUT HTTP_PROTOCOL      *HttpInstance,
  IN     NET_BUF            *Packet,
  IN     EFI_EVENT          Timeout
  )
{
  EFI_TCP4_RECEIVE_DATA     *Tcp4RxData;
  EFI_TCP6_RECEIVE_DATA     *Tcp6RxData;
  EFI_STATUS                Status;
  NET_FRAGMENT              *Fragment;
  UINT32                    FragmentCount;
  UINT32                    CurrentFragment;

  Tcp4RxData = NULL;
  Tcp6RxData = NULL;

  if ((HttpInstance == NULL) || (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  FragmentCount = Packet->BlockOpNum;
  Fragment      = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
  if (Fragment == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Build the fragment table.
  //
  NetbufBuildExt (Packet, Fragment, &FragmentCount);

  if (!HttpInstance->LocalAddressIsIPv6) {
    Tcp4RxData = HttpInstance->Tcp4TlsRxToken.Packet.RxData;
    if (Tcp4RxData == NULL) {
      return EFI_INVALID_PARAMETER;
    }
    Tcp4RxData->FragmentCount         = 1;
  } else {
    Tcp6RxData = HttpInstance->Tcp6TlsRxToken.Packet.RxData;
    if (Tcp6RxData == NULL) {
      return EFI_INVALID_PARAMETER;
    }
    Tcp6RxData->FragmentCount         = 1;
  }

  CurrentFragment               = 0;
  Status                        = EFI_SUCCESS;

  while (CurrentFragment < FragmentCount) {
    if (!HttpInstance->LocalAddressIsIPv6) {
      Tcp4RxData->DataLength                       = Fragment[CurrentFragment].Len;
      Tcp4RxData->FragmentTable[0].FragmentLength  = Fragment[CurrentFragment].Len;
      Tcp4RxData->FragmentTable[0].FragmentBuffer  = Fragment[CurrentFragment].Bulk;
      Status = HttpInstance->Tcp4->Receive (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken);
    } else {
      Tcp6RxData->DataLength                       = Fragment[CurrentFragment].Len;
      Tcp6RxData->FragmentTable[0].FragmentLength  = Fragment[CurrentFragment].Len;
      Tcp6RxData->FragmentTable[0].FragmentBuffer  = Fragment[CurrentFragment].Bulk;
      Status = HttpInstance->Tcp6->Receive (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken);
    }
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    while (!HttpInstance->TlsIsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
      //
      // Poll until some data is received or an error occurs.
      //
      if (!HttpInstance->LocalAddressIsIPv6) {
        HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
      } else {
        HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
      }
    }

    if (!HttpInstance->TlsIsRxDone) {
      //
      // Timeout occurs, cancel the receive request.
      //
      if (!HttpInstance->LocalAddressIsIPv6) {
        HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken.CompletionToken);
      } else {
        HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken.CompletionToken);
      }

      Status = EFI_TIMEOUT;
      goto ON_EXIT;
    } else {
      HttpInstance->TlsIsRxDone = FALSE;
    }

    if (!HttpInstance->LocalAddressIsIPv6) {
      Status = HttpInstance->Tcp4TlsRxToken.CompletionToken.Status;
      if (EFI_ERROR (Status)) {
        goto ON_EXIT;
      }

      Fragment[CurrentFragment].Len -= Tcp4RxData->FragmentTable[0].FragmentLength;
      if (Fragment[CurrentFragment].Len == 0) {
        CurrentFragment++;
      } else {
        Fragment[CurrentFragment].Bulk += Tcp4RxData->FragmentTable[0].FragmentLength;
      }
    } else {
      Status = HttpInstance->Tcp6TlsRxToken.CompletionToken.Status;
      if (EFI_ERROR (Status)) {
        goto ON_EXIT;
      }

      Fragment[CurrentFragment].Len -= Tcp6RxData->FragmentTable[0].FragmentLength;
      if (Fragment[CurrentFragment].Len == 0) {
        CurrentFragment++;
      } else {
        Fragment[CurrentFragment].Bulk += Tcp6RxData->FragmentTable[0].FragmentLength;
      }
    }
  }

ON_EXIT:

  if (Fragment != NULL) {
    FreePool (Fragment);
  }

  return Status;
}
Exemple #3
0
/**
  Transmit the Packet by processing the associated HTTPS token.

  @param[in, out]   HttpInstance    Pointer to HTTP_PROTOCOL structure.
  @param[in]        Packet          The packet to transmit.

  @retval EFI_SUCCESS            The packet is transmitted.
  @retval EFI_INVALID_PARAMETER  HttpInstance is NULL or Packet is NULL.
  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resources.
  @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.
  @retval Others                 Other errors as indicated.

**/
EFI_STATUS
EFIAPI
TlsCommonTransmit (
  IN OUT HTTP_PROTOCOL      *HttpInstance,
  IN     NET_BUF            *Packet
  )
{
  EFI_STATUS                Status;
  VOID                      *Data;
  UINTN                     Size;

  if ((HttpInstance == NULL) || (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if (!HttpInstance->LocalAddressIsIPv6) {
    Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +
           (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
  } else {
    Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
           (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
  }

  Data = AllocatePool (Size);
  if (Data == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  if (!HttpInstance->LocalAddressIsIPv6) {
    ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push        = TRUE;
    ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent      = FALSE;
    ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength  = Packet->TotalSize;

    //
    // Build the fragment table.
    //
    ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;

    NetbufBuildExt (
      Packet,
      (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0],
      &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount
      );

    HttpInstance->Tcp4TlsTxToken.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data;

    Status = EFI_DEVICE_ERROR;

    //
    // Transmit the packet.
    //
    Status  = HttpInstance->Tcp4->Transmit (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsTxToken);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    while (!HttpInstance->TlsIsTxDone) {
      HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
    }

    HttpInstance->TlsIsTxDone = FALSE;
    Status = HttpInstance->Tcp4TlsTxToken.CompletionToken.Status;
  } else {
    ((EFI_TCP6_TRANSMIT_DATA *) Data)->Push        = TRUE;
    ((EFI_TCP6_TRANSMIT_DATA *) Data)->Urgent      = FALSE;
    ((EFI_TCP6_TRANSMIT_DATA *) Data)->DataLength  = Packet->TotalSize;

    //
    // Build the fragment table.
    //
    ((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;

    NetbufBuildExt (
      Packet,
      (NET_FRAGMENT *) &((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentTable[0],
      &((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount
      );

    HttpInstance->Tcp6TlsTxToken.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data;

    Status = EFI_DEVICE_ERROR;

    //
    // Transmit the packet.
    //
    Status  = HttpInstance->Tcp6->Transmit (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsTxToken);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    while (!HttpInstance->TlsIsTxDone) {
      HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
    }

    HttpInstance->TlsIsTxDone = FALSE;
    Status = HttpInstance->Tcp6TlsTxToken.CompletionToken.Status;
  }

ON_EXIT:
  FreePool (Data);

  return Status;
}
Exemple #4
0
/**
  Receive data from the socket.

  @param[in, out]  TcpIo       The TcpIo which wraps the socket to be destroyed.
  @param[in]       Packet      The buffer to hold the data copy from the socket 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_INVALID_PARAMETER  One or more parameters are invalid.
  @retval EFI_DEVICE_ERROR       An unexpected network or system error occurred.
  @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
EFIAPI
TcpIoReceive (
  IN OUT TCP_IO             *TcpIo,
  IN     NET_BUF            *Packet,
  IN     BOOLEAN            AsyncMode,
  IN     EFI_EVENT          Timeout
  )
{
  EFI_TCP4_PROTOCOL         *Tcp4;
  EFI_TCP6_PROTOCOL         *Tcp6;
  EFI_TCP4_RECEIVE_DATA     *RxData;
  EFI_STATUS                Status;
  NET_FRAGMENT              *Fragment;
  UINT32                    FragmentCount;
  UINT32                    CurrentFragment;

  if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData;
  if (RxData == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Tcp4 = NULL;
  Tcp6 = NULL;

  if (TcpIo->TcpVersion == TCP_VERSION_4) {
    Tcp4 = TcpIo->Tcp.Tcp4;

    if (TcpIo->IsListenDone) {
      Tcp4 = TcpIo->NewTcp.Tcp4;
    }

    if (Tcp4 == NULL) {
      return EFI_DEVICE_ERROR;
    }

  } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
    Tcp6 = TcpIo->Tcp.Tcp6;

    if (TcpIo->IsListenDone) {
      Tcp6 = TcpIo->NewTcp.Tcp6;
    }

    if (Tcp6 == NULL) {
      return EFI_DEVICE_ERROR; 
    }

  } else {
    return EFI_UNSUPPORTED;
  }

  FragmentCount = Packet->BlockOpNum;
  Fragment      = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
  if (Fragment == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }
  //
  // Build the fragment table.
  //
  NetbufBuildExt (Packet, Fragment, &FragmentCount);

  RxData->FragmentCount         = 1;
  CurrentFragment               = 0;
  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;

    if (TcpIo->TcpVersion == TCP_VERSION_4) {
      Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token);
    } else {
      Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);
    }
    
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }
    
    while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
      //
      // Poll until some data is received or an error occurs.
      //
      if (TcpIo->TcpVersion == TCP_VERSION_4) {
        Tcp4->Poll (Tcp4);
      } else {
        Tcp6->Poll (Tcp6);
      }
    }

    if (!TcpIo->IsRxDone) {
      //
      // Timeout occurs, cancel the receive request.
      //
      if (TcpIo->TcpVersion == TCP_VERSION_4) {
        Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);
      } else {
        Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);
      }

      Status = EFI_TIMEOUT;
      goto ON_EXIT;
    } else {
      TcpIo->IsRxDone = FALSE;
    }

    Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;

    if (EFI_ERROR (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:

  if (Fragment != NULL) {
    FreePool (Fragment);
  }

  return Status;
}
Exemple #5
0
/**
  Transmit the Packet to the other endpoint of the socket.

  @param[in]   TcpIo           The TcpIo wrapping the TCP socket.
  @param[in]   Packet          The packet to transmit.
  
  @retval EFI_SUCCESS            The packet is trasmitted.
  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
  @retval EFI_UNSUPPORTED        One or more of the control options are not
                                 supported in the implementation.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
  @retval EFI_DEVICE_ERROR       An unexpected network or system error occurred.
  @retval Others                 Other errors as indicated.

**/
EFI_STATUS
EFIAPI
TcpIoTransmit (
  IN TCP_IO                 *TcpIo,
  IN NET_BUF                *Packet
  )
{
  EFI_STATUS                Status;
  VOID                      *Data;
  EFI_TCP4_PROTOCOL         *Tcp4;
  EFI_TCP6_PROTOCOL         *Tcp6;
  UINTN                     Size;

  if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if (TcpIo->TcpVersion == TCP_VERSION_4) {

    Size = sizeof (EFI_TCP4_TRANSMIT_DATA) + 
           (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
  } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
    Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
           (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
  } else {
    return EFI_UNSUPPORTED;
  }

  Data = AllocatePool (Size);
  if (Data == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push        = TRUE;
  ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent      = FALSE;
  ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength  = Packet->TotalSize;

  //
  // Build the fragment table.
  //
  ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;

  NetbufBuildExt (
    Packet,
    (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0],
    &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount
    );

  Tcp4   = NULL;
  Tcp6   = NULL;
  Status = EFI_DEVICE_ERROR;

  //
  // Trasnmit the packet.
  //
  if (TcpIo->TcpVersion == TCP_VERSION_4) {
    TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data;
    Tcp4    = TcpIo->Tcp.Tcp4;
    if (TcpIo->IsListenDone) {
      Tcp4 = TcpIo->NewTcp.Tcp4;
    }

    if (Tcp4 == NULL) {
      goto ON_EXIT;
    }
    
    Status  = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token);
  } else {
    TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data;
    Tcp6    = TcpIo->Tcp.Tcp6;
    if (TcpIo->IsListenDone) {
      Tcp6 = TcpIo->NewTcp.Tcp6;
    }

    if (Tcp6 == NULL) {
      goto ON_EXIT;
    }

    Status  = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);
  }

  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  while (!TcpIo->IsTxDone) {
    if (TcpIo->TcpVersion == TCP_VERSION_4) {
      Tcp4->Poll (Tcp4);
    } else {
      Tcp6->Poll (Tcp6);
    }
  }

  TcpIo->IsTxDone  = FALSE;
  Status           = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;

ON_EXIT:

  FreePool (Data);

  return Status;
}
Exemple #6
0
/**
  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:
  Tcp4Io->RxToken.Packet.RxData = NULL;
  FreePool (Fragment);

  return Status;
}