Beispiel #1
0
/**
  Build and send a ACK packet for the download session.

  @param  Instance              The Mtftp session
  @param  BlkNo                 The BlkNo to ack.

  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory for the packet
  @retval EFI_SUCCESS           The ACK has been sent
  @retval Others                Failed to send the ACK.

**/
EFI_STATUS
Mtftp4RrqSendAck (
  IN MTFTP4_PROTOCOL        *Instance,
  IN UINT16                 BlkNo
  )
{
  EFI_MTFTP4_PACKET         *Ack;
  NET_BUF                   *Packet;

  Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER));
  if (Packet == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Ack = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (
                                Packet,
                                sizeof (EFI_MTFTP4_ACK_HEADER),
                                FALSE
                                );
  ASSERT (Ack != NULL);

  Ack->Ack.OpCode   = HTONS (EFI_MTFTP4_OPCODE_ACK);
  Ack->Ack.Block[0] = HTONS (BlkNo);

  return Mtftp4SendPacket (Instance, Packet);
}
Beispiel #2
0
/**
  Build then send a MTFTP data packet for the MTFTP upload session.

  @param  Instance              The MTFTP upload session.
  @param  BlockNum              The block number to send.

  @retval EFI_OUT_OF_RESOURCES  Failed to build the packet.
  @retval EFI_ABORTED           The consumer of this child directs to abort the
                                transmission by return an error through PacketNeeded.
  @retval EFI_SUCCESS           The data is sent.

**/
EFI_STATUS
Mtftp4WrqSendBlock (
  IN OUT MTFTP4_PROTOCOL        *Instance,
  IN     UINT16                 BlockNum
  )
{
  EFI_MTFTP4_PACKET         *Packet;
  EFI_MTFTP4_TOKEN          *Token;
  NET_BUF                   *UdpPacket;
  EFI_STATUS                Status;
  UINT16                    DataLen;
  UINT8                     *DataBuf;
  UINT64                    Start;

  //
  // Allocate a buffer to hold the user data
  //
  UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP4_DATA_HEAD_LEN);

  if (UdpPacket == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);
  ASSERT (Packet != NULL);

  Packet->Data.OpCode = HTONS (EFI_MTFTP4_OPCODE_DATA);
  Packet->Data.Block  = HTONS (BlockNum);

  //
  // Read the block from either the buffer or PacketNeeded callback
  //
  Token   = Instance->Token;
  DataLen = Instance->BlkSize;

  if (Token->Buffer != NULL) {
    Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);

    if (Token->BufferSize < Start + Instance->BlkSize) {
      DataLen             = (UINT16) (Token->BufferSize - Start);
      Instance->LastBlock = BlockNum;
      Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
    }

    if (DataLen > 0) {
      NetbufAllocSpace (UdpPacket, DataLen, FALSE);
      CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
    }

  } else {
    //
    // Get data from PacketNeeded
    //
    DataBuf = NULL;
    Status  = Token->PacketNeeded (
                       &Instance->Mtftp4,
                       Token,
                       &DataLen,
                       (VOID **) &DataBuf
                       );

    if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
      if (DataBuf != NULL) {
        FreePool (DataBuf);
      }

      if (UdpPacket != NULL) {
        NetbufFree (UdpPacket);
      }

      Mtftp4SendError (
        Instance,
        EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
        (UINT8 *) "User aborted the transfer"
        );

      return EFI_ABORTED;
    }

    if (DataLen < Instance->BlkSize) {
      Instance->LastBlock = BlockNum;
      Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
    }

    if (DataLen > 0) {
      NetbufAllocSpace (UdpPacket, DataLen, FALSE);
      CopyMem (Packet->Data.Data, DataBuf, DataLen);
      FreePool (DataBuf);
    }
  }

  return Mtftp4SendPacket (Instance, UdpPacket);
}