]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Rrq.c
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
deleted file mode 100644 (file)
index 24c965a..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-/** @file\r
-  Routines to process Rrq (download).\r
-\r
-(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-\r
-#include "Mtftp4Impl.h"\r
-\r
-\r
-/**\r
-  The packet process callback for MTFTP download.\r
-\r
-  @param  UdpPacket             The packet received\r
-  @param  EndPoint              The local/remote access point of the packet\r
-  @param  IoStatus              The status of the receiving\r
-  @param  Context               Opaque parameter, which is the MTFTP session\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Mtftp4RrqInput (\r
-  IN NET_BUF                *UdpPacket,\r
-  IN UDP_END_POINT          *EndPoint,\r
-  IN EFI_STATUS             IoStatus,\r
-  IN VOID                   *Context\r
-  );\r
-\r
-\r
-/**\r
-  Start the MTFTP session to download.\r
-\r
-  It will first initialize some of the internal states then build and send a RRQ\r
-  reqeuest packet, at last, it will start receive for the downloading.\r
-\r
-  @param  Instance              The Mtftp session\r
-  @param  Operation             The MTFTP opcode, it may be a EFI_MTFTP4_OPCODE_RRQ\r
-                                or EFI_MTFTP4_OPCODE_DIR.\r
-\r
-  @retval EFI_SUCCESS           The mtftp download session is started.\r
-  @retval Others                Failed to start downloading.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4RrqStart (\r
-  IN MTFTP4_PROTOCOL        *Instance,\r
-  IN UINT16                 Operation\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // The valid block number range are [1, 0xffff]. For example:\r
-  // the client sends an RRQ request to the server, the server\r
-  // transfers the DATA1 block. If option negoitation is ongoing,\r
-  // the server will send back an OACK, then client will send ACK0.\r
-  //\r
-  Status = Mtftp4InitBlockRange (&Instance->Blocks, 1, 0xffff);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = Mtftp4SendRequest (Instance);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);\r
-}\r
-\r
-\r
-/**\r
-  Build and send a ACK packet for the download session.\r
-\r
-  @param  Instance              The Mtftp session\r
-  @param  BlkNo                 The BlkNo to ack.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory for the packet\r
-  @retval EFI_SUCCESS           The ACK has been sent\r
-  @retval Others                Failed to send the ACK.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4RrqSendAck (\r
-  IN MTFTP4_PROTOCOL        *Instance,\r
-  IN UINT16                 BlkNo\r
-  )\r
-{\r
-  EFI_MTFTP4_PACKET         *Ack;\r
-  NET_BUF                   *Packet;\r
-  EFI_STATUS                Status;\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER));\r
-  if (Packet == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Ack = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (\r
-                                Packet,\r
-                                sizeof (EFI_MTFTP4_ACK_HEADER),\r
-                                FALSE\r
-                                );\r
-  ASSERT (Ack != NULL);\r
-\r
-  Ack->Ack.OpCode   = HTONS (EFI_MTFTP4_OPCODE_ACK);\r
-  Ack->Ack.Block[0] = HTONS (BlkNo);\r
-\r
-  Status = Mtftp4SendPacket (Instance, Packet);\r
-  if (!EFI_ERROR (Status)) {\r
-    Instance->AckedBlock = Instance->TotalBlock;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Deliver the received data block to the user, which can be saved\r
-  in the user provide buffer or through the CheckPacket callback.\r
-\r
-  @param  Instance              The Mtftp session\r
-  @param  Packet                The received data packet\r
-  @param  Len                   The packet length\r
-\r
-  @retval EFI_SUCCESS           The data is saved successfully\r
-  @retval EFI_ABORTED           The user tells to abort by return an error  through\r
-                                CheckPacket\r
-  @retval EFI_BUFFER_TOO_SMALL  The user's buffer is too small and buffer length is\r
-                                 updated to the actual buffer size needed.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4RrqSaveBlock (\r
-  IN OUT MTFTP4_PROTOCOL        *Instance,\r
-  IN     EFI_MTFTP4_PACKET      *Packet,\r
-  IN     UINT32                 Len\r
-  )\r
-{\r
-  EFI_MTFTP4_TOKEN          *Token;\r
-  EFI_STATUS                Status;\r
-  UINT16                    Block;\r
-  UINT64                    Start;\r
-  UINT32                    DataLen;\r
-  UINT64                    BlockCounter;\r
-  BOOLEAN                   Completed;\r
-\r
-  Completed = FALSE;\r
-  Token     = Instance->Token;\r
-  Block     = NTOHS (Packet->Data.Block);\r
-  DataLen   = Len - MTFTP4_DATA_HEAD_LEN;\r
-\r
-  //\r
-  // This is the last block, save the block no\r
-  //\r
-  if (DataLen < Instance->BlkSize) {\r
-    Completed = TRUE;\r
-    Instance->LastBlock = Block;\r
-    Mtftp4SetLastBlockNum (&Instance->Blocks, Block);\r
-  }\r
-\r
-  //\r
-  // Remove this block number from the file hole. If Mtftp4RemoveBlockNum\r
-  // returns EFI_NOT_FOUND, the block has been saved, don't save it again.\r
-  // Note that : For bigger files, allowing the block counter to roll over\r
-  // to accept transfers of unlimited size. So BlockCounter is memorised as\r
-  // continuous block counter.\r
-  //\r
-  Status = Mtftp4RemoveBlockNum (&Instance->Blocks, Block, Completed, &BlockCounter);\r
-\r
-  if (Status == EFI_NOT_FOUND) {\r
-    return EFI_SUCCESS;\r
-  } else if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (Token->CheckPacket != NULL) {\r
-    Status = Token->CheckPacket (&Instance->Mtftp4, Token, (UINT16) Len, Packet);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Mtftp4SendError (\r
-        Instance,\r
-        EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,\r
-        (UINT8 *) "User aborted download"\r
-        );\r
-\r
-      return EFI_ABORTED;\r
-    }\r
-  }\r
-\r
-  if (Token->Buffer != NULL) {\r
-     Start = MultU64x32 (BlockCounter - 1, Instance->BlkSize);\r
-\r
-    if (Start + DataLen <= Token->BufferSize) {\r
-      CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen);\r
-\r
-      //\r
-      // Update the file size when received the last block\r
-      //\r
-      if ((Instance->LastBlock == Block) && Completed) {\r
-        Token->BufferSize = Start + DataLen;\r
-      }\r
-\r
-    } else if (Instance->LastBlock != 0) {\r
-      //\r
-      // Don't save the data if the buffer is too small, return\r
-      // EFI_BUFFER_TOO_SMALL if received the last packet. This\r
-      // will give a accurate file length.\r
-      //\r
-      Token->BufferSize = Start + DataLen;\r
-\r
-      Mtftp4SendError (\r
-        Instance,\r
-        EFI_MTFTP4_ERRORCODE_DISK_FULL,\r
-        (UINT8 *) "User provided memory block is too small"\r
-        );\r
-\r
-      return EFI_BUFFER_TOO_SMALL;\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Function to process the received data packets.\r
-\r
-  It will save the block then send back an ACK if it is active.\r
-\r
-  @param  Instance              The downloading MTFTP session\r
-  @param  Packet                The packet received\r
-  @param  Len                   The length of the packet\r
-  @param  Multicast             Whether this packet is multicast or unicast\r
-  @param  Completed             Return whether the download has completed\r
-\r
-  @retval EFI_SUCCESS           The data packet is successfully processed\r
-  @retval EFI_ABORTED           The download is aborted by the user\r
-  @retval EFI_BUFFER_TOO_SMALL  The user provided buffer is too small\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4RrqHandleData (\r
-  IN     MTFTP4_PROTOCOL       *Instance,\r
-  IN     EFI_MTFTP4_PACKET     *Packet,\r
-  IN     UINT32                Len,\r
-  IN     BOOLEAN               Multicast,\r
-     OUT BOOLEAN               *Completed\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  UINT16                    BlockNum;\r
-  INTN                      Expected;\r
-\r
-  *Completed  = FALSE;\r
-  Status      = EFI_SUCCESS;\r
-  BlockNum    = NTOHS (Packet->Data.Block);\r
-  Expected    = Mtftp4GetNextBlockNum (&Instance->Blocks);\r
-\r
-  ASSERT (Expected >= 0);\r
-\r
-  //\r
-  // If we are active (Master) and received an unexpected packet, transmit\r
-  // the ACK for the block we received, then restart receiving the\r
-  // expected one. If we are passive (Slave), save the block.\r
-  //\r
-  if (Instance->Master && (Expected != BlockNum)) {\r
-    //\r
-    // If Expected is 0, (UINT16) (Expected - 1) is also the expected Ack number (65535).\r
-    //\r
-    return Mtftp4RrqSendAck (Instance,  (UINT16) (Expected - 1));\r
-  }\r
-\r
-  Status = Mtftp4RrqSaveBlock (Instance, Packet, Len);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Record the total received and saved block number.\r
-  //\r
-  Instance->TotalBlock ++;\r
-\r
-  //\r
-  // Reset the passive client's timer whenever it received a\r
-  // valid data packet.\r
-  //\r
-  if (!Instance->Master) {\r
-    Mtftp4SetTimeout (Instance);\r
-  }\r
-\r
-  //\r
-  // Check whether we have received all the blocks. Send the ACK if we\r
-  // are active (unicast client or master client for multicast download).\r
-  // If we have received all the blocks, send an ACK even if we are passive\r
-  // to tell the server that we are done.\r
-  //\r
-  Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);\r
-\r
-  if (Instance->Master || (Expected < 0)) {\r
-    if (Expected < 0) {\r
-      //\r
-      // If we are passive client, then the just received Block maybe\r
-      // isn't the last block. We need to send an ACK to the last block\r
-      // to inform the server that we are done. If we are active client,\r
-      // the Block == Instance->LastBlock.\r
-      //\r
-      BlockNum   = Instance->LastBlock;\r
-      *Completed = TRUE;\r
-\r
-    } else {\r
-      BlockNum = (UINT16) (Expected - 1);\r
-    }\r
-\r
-    if (Instance->WindowSize == (Instance->TotalBlock - Instance->AckedBlock) || Expected < 0) {\r
-      Status = Mtftp4RrqSendAck (Instance, BlockNum);\r
-    }\r
-\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Validate whether the options received in the server's OACK packet is valid.\r
-\r
-  The options are valid only if:\r
-  1. The server doesn't include options not requested by us\r
-  2. The server can only use smaller blksize than that is requested\r
-  3. The server can only use the same timeout as requested\r
-  4. The server doesn't change its multicast channel.\r
-\r
-  @param  This                  The downloading Mtftp session\r
-  @param  Reply                 The options in the OACK packet\r
-  @param  Request               The requested options\r
-\r
-  @retval TRUE                  The options in the OACK is OK.\r
-  @retval FALSE                 The options in the OACK is invalid.\r
-\r
-**/\r
-BOOLEAN\r
-Mtftp4RrqOackValid (\r
-  IN MTFTP4_PROTOCOL        *This,\r
-  IN MTFTP4_OPTION          *Reply,\r
-  IN MTFTP4_OPTION          *Request\r
-  )\r
-{\r
-\r
-  //\r
-  // It is invalid for server to return options we don't request\r
-  //\r
-  if ((Reply->Exist &~Request->Exist) != 0) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Server can only specify a smaller block size and window size to be used and\r
-  // return the timeout matches that requested.\r
-  //\r
-  if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0)&& (Reply->BlkSize > Request->BlkSize)) ||\r
-      (((Reply->Exist & MTFTP4_WINDOWSIZE_EXIST) != 0)&& (Reply->WindowSize > Request->WindowSize)) ||\r
-      (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))\r
-     ) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // The server can send ",,master" to client to change its master\r
-  // setting. But if it use the specific multicast channel, it can't\r
-  // change the setting.\r
-  //\r
-  if (((Reply->Exist & MTFTP4_MCAST_EXIST) != 0) && (This->McastIp != 0)) {\r
-    if ((Reply->McastIp != 0) && (Reply->McastIp != This->McastIp)) {\r
-      return FALSE;\r
-    }\r
-\r
-    if ((Reply->McastPort != 0) && (Reply->McastPort != This->McastPort)) {\r
-      return FALSE;\r
-    }\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-\r
-/**\r
-  Configure a UDP IO port to receive the multicast.\r
-\r
-  @param  McastIo               The UDP IO to configure\r
-  @param  Context               The opaque parameter to the function which is the\r
-                                MTFTP session.\r
-\r
-  @retval EFI_SUCCESS           The UDP child is successfully configured.\r
-  @retval Others                Failed to configure the UDP child.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Mtftp4RrqConfigMcastPort (\r
-  IN UDP_IO                 *McastIo,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  EFI_MTFTP4_CONFIG_DATA    *Config;\r
-  EFI_UDP4_CONFIG_DATA      UdpConfig;\r
-  EFI_IPv4_ADDRESS          Group;\r
-  EFI_STATUS                Status;\r
-  IP4_ADDR                  Ip;\r
-\r
-  Instance                     = (MTFTP4_PROTOCOL *) Context;\r
-  Config                       = &Instance->Config;\r
-\r
-  UdpConfig.AcceptBroadcast    = FALSE;\r
-  UdpConfig.AcceptPromiscuous  = FALSE;\r
-  UdpConfig.AcceptAnyPort      = FALSE;\r
-  UdpConfig.AllowDuplicatePort = FALSE;\r
-  UdpConfig.TypeOfService      = 0;\r
-  UdpConfig.TimeToLive         = 64;\r
-  UdpConfig.DoNotFragment      = FALSE;\r
-  UdpConfig.ReceiveTimeout     = 0;\r
-  UdpConfig.TransmitTimeout    = 0;\r
-  UdpConfig.UseDefaultAddress  = Config->UseDefaultSetting;\r
-  IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);\r
-  IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);\r
-  UdpConfig.StationPort        = Instance->McastPort;\r
-  UdpConfig.RemotePort         = 0;\r
-\r
-  Ip = HTONL (Instance->ServerIp);\r
-  IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);\r
-\r
-  Status = McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, &UdpConfig);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (!Config->UseDefaultSetting &&\r
-      !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {\r
-    //\r
-    // The station IP address is manually configured and the Gateway IP is not 0.\r
-    // Add the default route for this UDP instance.\r
-    //\r
-    Status = McastIo->Protocol.Udp4->Routes (\r
-                                       McastIo->Protocol.Udp4,\r
-                                       FALSE,\r
-                                       &mZeroIp4Addr,\r
-                                       &mZeroIp4Addr,\r
-                                       &Config->GatewayIp\r
-                                       );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, NULL);\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  //\r
-  // join the multicast group\r
-  //\r
-  Ip = HTONL (Instance->McastIp);\r
-  IP4_COPY_ADDRESS (&Group, &Ip);\r
-\r
-  return McastIo->Protocol.Udp4->Groups (McastIo->Protocol.Udp4, TRUE, &Group);\r
-}\r
-\r
-\r
-/**\r
-  Function to process the OACK.\r
-\r
-  It will first validate the OACK packet, then update the various negotiated parameters.\r
-\r
-  @param  Instance              The download MTFTP session\r
-  @param  Packet                The packet received\r
-  @param  Len                   The packet length\r
-  @param  Multicast             Whether this packet is received as a multicast\r
-  @param  Completed             Returns whether the download has completed. NOT\r
-                                used  by this function.\r
-\r
-  @retval EFI_DEVICE_ERROR      Failed to create/start a multicast UDP child\r
-  @retval EFI_TFTP_ERROR        Some error happened during the process\r
-  @retval EFI_SUCCESS           The OACK is successfully processed.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4RrqHandleOack (\r
-  IN OUT MTFTP4_PROTOCOL       *Instance,\r
-  IN     EFI_MTFTP4_PACKET     *Packet,\r
-  IN     UINT32                Len,\r
-  IN     BOOLEAN               Multicast,\r
-     OUT BOOLEAN               *Completed\r
-  )\r
-{\r
-  MTFTP4_OPTION             Reply;\r
-  EFI_STATUS                Status;\r
-  INTN                      Expected;\r
-  EFI_UDP4_PROTOCOL         *Udp4;\r
-\r
-  *Completed = FALSE;\r
-\r
-  //\r
-  // If already started the master download, don't change the\r
-  // setting. Master download always succeeds.\r
-  //\r
-  Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);\r
-  ASSERT (Expected != -1);\r
-\r
-  if (Instance->Master && (Expected != 1)) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Parse and validate the options from server\r
-  //\r
-  ZeroMem (&Reply, sizeof (MTFTP4_OPTION));\r
-\r
-  Status = Mtftp4ParseOptionOack (Packet, Len, Instance->Operation, &Reply);\r
-\r
-  if (EFI_ERROR (Status) ||\r
-      !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) {\r
-    //\r
-    // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.\r
-    //\r
-    if (Status != EFI_OUT_OF_RESOURCES) {\r
-      Mtftp4SendError (\r
-        Instance,\r
-        EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,\r
-        (UINT8 *) "Mal-formated OACK packet"\r
-        );\r
-    }\r
-\r
-    return EFI_TFTP_ERROR;\r
-  }\r
-\r
-  if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) {\r
-\r
-    //\r
-    // Save the multicast info. Always update the Master, only update the\r
-    // multicast IP address, block size, window size, timeoute at the first time. If IP\r
-    // address is updated, create a UDP child to receive the multicast.\r
-    //\r
-    Instance->Master = Reply.Master;\r
-\r
-    if (Instance->McastIp == 0) {\r
-      if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) {\r
-        Mtftp4SendError (\r
-          Instance,\r
-          EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,\r
-          (UINT8 *) "Illegal multicast setting"\r
-          );\r
-\r
-        return EFI_TFTP_ERROR;\r
-      }\r
-\r
-      //\r
-      // Create a UDP child then start receive the multicast from it.\r
-      //\r
-      Instance->McastIp      = Reply.McastIp;\r
-      Instance->McastPort    = Reply.McastPort;\r
-      if (Instance->McastUdpPort == NULL) {\r
-        Instance->McastUdpPort = UdpIoCreateIo (\r
-                                   Instance->Service->Controller,\r
-                                   Instance->Service->Image,\r
-                                   Mtftp4RrqConfigMcastPort,\r
-                                   UDP_IO_UDP4_VERSION,\r
-                                   Instance\r
-                                   );\r
-        if (Instance->McastUdpPort != NULL) {\r
-          Status = gBS->OpenProtocol (\r
-                          Instance->McastUdpPort->UdpHandle,\r
-                          &gEfiUdp4ProtocolGuid,\r
-                          (VOID **) &Udp4,\r
-                          Instance->Service->Image,\r
-                          Instance->Handle,\r
-                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                          );\r
-          if (EFI_ERROR (Status)) {\r
-            UdpIoFreeIo (Instance->McastUdpPort);\r
-            Instance->McastUdpPort = NULL;\r
-            return EFI_DEVICE_ERROR;\r
-          }\r
-        }\r
-      }\r
-\r
-\r
-      if (Instance->McastUdpPort == NULL) {\r
-        return EFI_DEVICE_ERROR;\r
-      }\r
-\r
-      Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        Mtftp4SendError (\r
-          Instance,\r
-          EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION,\r
-          (UINT8 *) "Failed to create socket to receive multicast packet"\r
-          );\r
-\r
-        return Status;\r
-      }\r
-\r
-      //\r
-      // Update the parameters used.\r
-      //\r
-      if (Reply.BlkSize != 0) {\r
-        Instance->BlkSize = Reply.BlkSize;\r
-      }\r
-\r
-      if (Reply.WindowSize != 0) {\r
-        Instance->WindowSize = Reply.WindowSize;\r
-      }\r
-\r
-      if (Reply.Timeout != 0) {\r
-        Instance->Timeout = Reply.Timeout;\r
-      }\r
-    }\r
-\r
-  } else {\r
-    Instance->Master = TRUE;\r
-\r
-    if (Reply.BlkSize != 0) {\r
-      Instance->BlkSize = Reply.BlkSize;\r
-    }\r
-\r
-    if (Reply.WindowSize != 0) {\r
-      Instance->WindowSize = Reply.WindowSize;\r
-    }\r
-\r
-    if (Reply.Timeout != 0) {\r
-      Instance->Timeout = Reply.Timeout;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Send an ACK to (Expected - 1) which is 0 for unicast download,\r
-  // or tell the server we want to receive the Expected block.\r
-  //\r
-  return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1));\r
-}\r
-\r
-\r
-/**\r
-  The packet process callback for MTFTP download.\r
-\r
-  @param  UdpPacket             The packet received\r
-  @param  EndPoint              The local/remote access point of the packet\r
-  @param  IoStatus              The status of the receiving\r
-  @param  Context               Opaque parameter, which is the MTFTP session\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Mtftp4RrqInput (\r
-  IN NET_BUF                *UdpPacket,\r
-  IN UDP_END_POINT          *EndPoint,\r
-  IN EFI_STATUS             IoStatus,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  EFI_MTFTP4_PACKET         *Packet;\r
-  BOOLEAN                   Completed;\r
-  BOOLEAN                   Multicast;\r
-  EFI_STATUS                Status;\r
-  UINT16                    Opcode;\r
-  UINT32                    Len;\r
-\r
-  Instance  = (MTFTP4_PROTOCOL *) Context;\r
-  NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);\r
-\r
-  Status    = EFI_SUCCESS;\r
-  Packet    = NULL;\r
-  Completed = FALSE;\r
-  Multicast = FALSE;\r
-\r
-  if (EFI_ERROR (IoStatus)) {\r
-    Status = IoStatus;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  ASSERT (UdpPacket != NULL);\r
-\r
-  //\r
-  // Find the port this packet is from to restart receive correctly.\r
-  //\r
-  Multicast = (BOOLEAN) (EndPoint->LocalAddr.Addr[0] == Instance->McastIp);\r
-\r
-  if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Client send initial request to server's listening port. Server\r
-  // will select a UDP port to communicate with the client. The server\r
-  // is required to use the same port as RemotePort to multicast the\r
-  // data.\r
-  //\r
-  if (EndPoint->RemotePort != Instance->ConnectedPort) {\r
-    if (Instance->ConnectedPort != 0) {\r
-      goto ON_EXIT;\r
-    } else {\r
-      Instance->ConnectedPort = EndPoint->RemotePort;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Copy the MTFTP packet to a continuous buffer if it isn't already so.\r
-  //\r
-  Len = UdpPacket->TotalSize;\r
-\r
-  if (UdpPacket->BlockOpNum > 1) {\r
-    Packet = AllocatePool (Len);\r
-\r
-    if (Packet == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto ON_EXIT;\r
-    }\r
-\r
-    NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);\r
-\r
-  } else {\r
-    Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);\r
-    ASSERT (Packet != NULL);\r
-  }\r
-\r
-  Opcode = NTOHS (Packet->OpCode);\r
-\r
-  //\r
-  // Call the user's CheckPacket if provided. Abort the transmission\r
-  // if CheckPacket returns an EFI_ERROR code.\r
-  //\r
-  if ((Instance->Token->CheckPacket != NULL) &&\r
-      ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {\r
-\r
-    Status = Instance->Token->CheckPacket (\r
-                                &Instance->Mtftp4,\r
-                                Instance->Token,\r
-                                (UINT16) Len,\r
-                                Packet\r
-                                );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // Send an error message to the server to inform it\r
-      //\r
-      if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {\r
-        Mtftp4SendError (\r
-          Instance,\r
-          EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,\r
-          (UINT8 *) "User aborted the transfer"\r
-          );\r
-      }\r
-\r
-      Status = EFI_ABORTED;\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  switch (Opcode) {\r
-  case EFI_MTFTP4_OPCODE_DATA:\r
-    if ((Len > (UINT32) (MTFTP4_DATA_HEAD_LEN + Instance->BlkSize)) ||\r
-        (Len < (UINT32) MTFTP4_DATA_HEAD_LEN)) {\r
-      goto ON_EXIT;\r
-    }\r
-\r
-    Status = Mtftp4RrqHandleData (Instance, Packet, Len, Multicast, &Completed);\r
-    break;\r
-\r
-  case EFI_MTFTP4_OPCODE_OACK:\r
-    if (Multicast || (Len <= MTFTP4_OPCODE_LEN)) {\r
-      goto ON_EXIT;\r
-    }\r
-\r
-    Status = Mtftp4RrqHandleOack (Instance, Packet, Len, Multicast, &Completed);\r
-    break;\r
-\r
-  case EFI_MTFTP4_OPCODE_ERROR:\r
-    Status = EFI_TFTP_ERROR;\r
-    break;\r
-\r
-  default:\r
-    break;\r
-  }\r
-\r
-ON_EXIT:\r
-\r
-  //\r
-  // Free the resources, then if !EFI_ERROR (Status), restart the\r
-  // receive, otherwise end the session.\r
-  //\r
-  if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {\r
-    FreePool (Packet);\r
-  }\r
-\r
-  if (UdpPacket != NULL) {\r
-    NetbufFree (UdpPacket);\r
-  }\r
-\r
-  if (!EFI_ERROR (Status) && !Completed) {\r
-    if (Multicast) {\r
-      Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);\r
-    } else {\r
-      Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);\r
-    }\r
-  }\r
-\r
-  if (EFI_ERROR (Status) || Completed) {\r
-    Mtftp4CleanOperation (Instance, Status);\r
-  }\r
-}\r