mtftp4support.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 667 行 · 第 1/2 页

C
667
字号
  Packet->OpCode = HTONS (Instance->Operation);
  Cur            = Packet->Rrq.Filename;
  Cur            = EfiAsciiStrCpy (Cur, Token->Filename);
  Cur            = EfiAsciiStrCpy (Cur, Mode);

  for (Index = 0; Index < Token->OptionCount; ++Index) {
    Cur = EfiAsciiStrCpy (Cur, Options[Index].OptionStr);
    Cur = EfiAsciiStrCpy (Cur, Options[Index].ValueStr);
  }

  return Mtftp4SendPacket (Instance, Nbuf);
}

EFI_STATUS
Mtftp4SendError (
  IN MTFTP4_PROTOCOL        *Instance,
  IN UINT16                 ErrCode,
  IN UINT8*                 ErrInfo
  )
/*++

Routine Description:

  Build then send an error message 

Arguments:

  Instance  - The MTFTP session
  ErrInfo   - The error code and message

Returns:

  EFI_OUT_OF_RESOURCES - Failed to allocate memory for the error packet
  EFI_SUCCESS          - The error packet is transmitted.
  Others               - Failed to transmit the packet.

--*/
{
  NET_BUF                   *Packet;
  EFI_MTFTP4_PACKET         *TftpError;
  UINT32                    Len;

  Len     = (UINT32) (EfiAsciiStrLen (ErrInfo) + sizeof (EFI_MTFTP4_ERROR_HEADER));
  Packet  = NetbufAlloc (Len);

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

  TftpError         = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Packet, Len, FALSE);
  TftpError->OpCode = HTONS (EFI_MTFTP4_OPCODE_ERROR);
  TftpError->Error.ErrorCode = HTONS (ErrCode);

  EfiAsciiStrCpy (TftpError->Error.ErrorMessage, ErrInfo);

  return Mtftp4SendPacket (Instance, Packet);
}

STATIC
VOID
Mtftp4OnPacketSent (
  NET_BUF                   *Packet,
  UDP_POINTS                *Points,
  EFI_STATUS                IoStatus,
  VOID                      *Context
  )
/*++

Routine Description:

  The callback function called when the packet is transmitted.
  It simply frees the packet.

Arguments:

  Packet    - The transmitted (or failed to) packet
  Points    - The local and remote UDP access point 
  IoStatus  - The result of the transmission
  Context   - Opaque parameter to the callback

Returns:

  None

--*/
{
  NetbufFree (Packet);
}

VOID
Mtftp4SetTimeout (
  IN MTFTP4_PROTOCOL        *Instance
  )
/*++

Routine Description:

  Set the timeout for the instance. User a longer time for 
  passive instances.

Arguments:

  Instance  - The Mtftp session to set time out

Returns:

  None

--*/
{
  if (Instance->Master) {
    Instance->PacketToLive = Instance->Timeout;
  } else {
    Instance->PacketToLive = Instance->Timeout * 2;
  }
}

EFI_STATUS
Mtftp4SendPacket (
  IN MTFTP4_PROTOCOL        *Instance,
  IN NET_BUF                *Packet
  )
/*++

Routine Description:

  Send the packet for the instance. It will first save a reference to 
  the packet for later retransmission. then determine the destination 
  port, listen port for requests, and connected port for others. At last, 
  send the packet out.

Arguments:

  Instance  - The Mtftp instance
  Packet    - The packet to send

Returns:

  EFI_SUCCESS - The packet is sent out
  Others      - Failed to transmit the packet.

--*/
{
  UDP_POINTS                UdpPoint;
  EFI_STATUS                Status;
  UINT16                    OpCode;

  //
  // Save the packet for retransmission
  //
  if (Instance->LastPacket != NULL) {
    NetbufFree (Instance->LastPacket);
  }

  Instance->LastPacket  = Packet;
  
  Instance->CurRetry    = 0;
  Mtftp4SetTimeout (Instance);

  UdpPoint.LocalAddr    = 0;
  UdpPoint.LocalPort    = 0;
  UdpPoint.RemoteAddr   = Instance->ServerIp;

  //
  // Send the requests to the listening port, other packets 
  // to the connected port
  //
  OpCode = NTOHS (*((UINT16 *) NetbufGetByte (Packet, 0, NULL)));

  if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || (OpCode == EFI_MTFTP4_OPCODE_DIR) || 
      (OpCode == EFI_MTFTP4_OPCODE_WRQ)) {
    UdpPoint.RemotePort = Instance->ListeningPort;
  } else {
    UdpPoint.RemotePort = Instance->ConnectedPort;
  }

  NET_GET_REF (Packet);

  Status = UdpIoSendDatagram (
             Instance->UnicastPort,
             Packet,
             &UdpPoint,
             Instance->Gateway,
             Mtftp4OnPacketSent,
             Instance
             );

  if (EFI_ERROR (Status)) {
    NET_PUT_REF (Packet);
  }

  return Status;
}

EFI_STATUS
Mtftp4Retransmit (
  IN MTFTP4_PROTOCOL        *Instance
  )
/*++

Routine Description:

  Retransmit the last packet for the instance

Arguments:

  Instance  - The Mtftp instance

Returns:

  EFI_SUCCESS - The last packet is retransmitted.
  Others      - Failed to retransmit.

--*/
{
  UDP_POINTS                UdpPoint;
  EFI_STATUS                Status;
  UINT16                    OpCode;

  ASSERT (Instance->LastPacket != NULL);

  UdpPoint.LocalAddr  = 0;
  UdpPoint.LocalPort  = 0;
  UdpPoint.RemoteAddr = Instance->ServerIp;

  //
  // Set the requests to the listening port, other packets to the connected port
  //
  OpCode = NTOHS (*(UINT16 *) NetbufGetByte (Instance->LastPacket, 0, NULL));

  if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || (OpCode == EFI_MTFTP4_OPCODE_DIR) || 
      (OpCode == EFI_MTFTP4_OPCODE_WRQ)) {
    UdpPoint.RemotePort = Instance->ListeningPort;
  } else {
    UdpPoint.RemotePort = Instance->ConnectedPort;
  }

  NET_GET_REF (Instance->LastPacket);
  
  Status = UdpIoSendDatagram (
             Instance->UnicastPort,
             Instance->LastPacket,
             &UdpPoint,
             Instance->Gateway,
             Mtftp4OnPacketSent,
             Instance
             );

  if (EFI_ERROR (Status)) {
    NET_PUT_REF (Instance->LastPacket);
  }

  return Status;
}

VOID
EFIAPI
Mtftp4OnTimerTick (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  )
/*++

Routine Description:

  The timer ticking function for the Mtftp service instance.

Arguments:

  Event   - The ticking event 
  Context - The Mtftp service instance

Returns:

  None

--*/
{
  MTFTP4_SERVICE            *MtftpSb;
  NET_LIST_ENTRY            *Entry;
  NET_LIST_ENTRY            *Next;
  MTFTP4_PROTOCOL           *Instance;
  EFI_MTFTP4_TOKEN          *Token;
  EFI_TPL                   OldTpl;

  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);
  MtftpSb = (MTFTP4_SERVICE *) Context;

  //
  // Iterate through all the children of the Mtftp service instance. Time
  // out the packet. If maximum retries reached, clean the session up.
  //
  NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {
    Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);

    if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {
      continue;
    }

    //
    // Call the user's time out handler
    //
    Token = Instance->Token;
    
    if ((Token->TimeoutCallback != NULL) &&
        EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token))) {

      Mtftp4SendError (
         Instance, 
         EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
         "User aborted the transfer in time out"
         );

      Mtftp4CleanOperation (Instance, EFI_ABORTED);
      continue;
    }

    //
    // Retransmit the packet if haven't reach the maxmium retry count,
    // otherwise exit the transfer.
    //
    if (++Instance->CurRetry < Instance->MaxRetry) {
      Mtftp4Retransmit (Instance);
      Mtftp4SetTimeout (Instance);
    } else {
      Mtftp4CleanOperation (Instance, EFI_TIMEOUT);
      continue;
    }
  }

  NET_RESTORE_TPL (OldTpl);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?