]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c
Retiring the ANT/JAVA build and removing the older EDK II packages that required...
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeBc / Dxe / pxe_bc_mtftp.c
diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c
deleted file mode 100644 (file)
index e2afbff..0000000
+++ /dev/null
@@ -1,2379 +0,0 @@
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
-    pxe_bc_mtftp.c\r
-\r
-Abstract:\r
-  TFTP and MTFTP (multicast TFTP) implementation.\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-\r
-//\r
-// The following #define is used to create a version that does not wait to\r
-// open after a listen.  This is just for a special regression test of MTFTP\r
-// server to make sure multiple opens are handled correctly.  Normally this\r
-// next line should be a comment.\r
-// #define SpecialNowaitVersion    // comment out for normal operation\r
-//\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-\r
-\r
-#include "Bc.h"\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-UINT64\r
-Swap64 (\r
-  UINT64 n\r
-  )\r
-{\r
-  union {\r
-    UINT64  n;\r
-    UINT8   b[8];\r
-  } u;\r
-\r
-  UINT8 t;\r
-\r
-  u.n     = n;\r
-\r
-  t       = u.b[0];\r
-  u.b[0]  = u.b[7];\r
-  u.b[7]  = t;\r
-\r
-  t       = u.b[1];\r
-  u.b[1]  = u.b[6];\r
-  u.b[6]  = t;\r
-\r
-  t       = u.b[2];\r
-  u.b[2]  = u.b[5];\r
-  u.b[5]  = t;\r
-\r
-  t       = u.b[3];\r
-  u.b[3]  = u.b[4];\r
-  u.b[4]  = t;\r
-\r
-  return u.n;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-TftpUdpRead (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  UINT16                      Operation,\r
-  VOID                        *HeaderPtr,\r
-  UINTN                       *BufferSizePtr,\r
-  VOID                        *BufferPtr,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_IP_ADDRESS              *OurIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr,\r
-  UINT16                      Timeout\r
-  )\r
-/*++\r
-Routine description:\r
-  Read TFTP packet.  If TFTP ERROR packet is read, fill in TFTP error\r
-  information in Mode structure and return TFTP_ERROR status.\r
-\r
-Parameters:\r
-  Private :=\r
-  Operation :=\r
-  HeaderPtr :=\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr :=\r
-  ServerPortPtr :=\r
-  OurIpPtr :=\r
-  OurPortPtr :=\r
-  Timeout :=\r
-\r
-Returns:\r
-  EFI_SUCCESS :=\r
-  EFI_TFTP_ERROR :=\r
-  other :=\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_MODE  *PxeBcMode;\r
-  EFI_STATUS              Status;\r
-  EFI_EVENT               TimeoutEvent;\r
-  UINTN                   HeaderSize;\r
-\r
-  //\r
-  //\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  NULL,\r
-                  NULL,\r
-                  &TimeoutEvent\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->SetTimer (\r
-                  TimeoutEvent,\r
-                  TimerRelative,\r
-                  Timeout * 10000000 + 1000000\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseEvent (TimeoutEvent);\r
-    return Status;\r
-  }\r
-  //\r
-  //\r
-  //\r
-  HeaderSize = Private->BigBlkNumFlag ? sizeof (struct Tftpv4Ack8) : sizeof (struct Tftpv4Ack);\r
-\r
-#define ERROR_MESSAGE_PTR ((struct Tftpv4Error *) HeaderPtr)\r
-\r
-  Status = UdpRead (\r
-            Private,\r
-            Operation,\r
-            OurIpPtr,\r
-            OurPortPtr,\r
-            ServerIpPtr,\r
-            ServerPortPtr,\r
-            &HeaderSize,\r
-            HeaderPtr,\r
-            BufferSizePtr,\r
-            BufferPtr,\r
-            TimeoutEvent\r
-            );\r
-\r
-  if (Status != EFI_SUCCESS || ERROR_MESSAGE_PTR->OpCode != HTONS (TFTP_ERROR)) {\r
-    gBS->CloseEvent (TimeoutEvent);\r
-    return Status;\r
-  }\r
-  //\r
-  // got an error packet\r
-  // write one byte error code followed by error message\r
-  //\r
-  PxeBcMode                       = Private->EfiBc.Mode;\r
-  PxeBcMode->TftpErrorReceived    = TRUE;\r
-  PxeBcMode->TftpError.ErrorCode  = (UINT8) NTOHS (ERROR_MESSAGE_PTR->ErrCode);\r
-  HeaderSize                      = EFI_MIN (*BufferSizePtr, sizeof PxeBcMode->TftpError.ErrorString);\r
-  CopyMem (PxeBcMode->TftpError.ErrorString, BufferPtr, HeaderSize);\r
-\r
-  gBS->CloseEvent (TimeoutEvent);\r
-  return EFI_TFTP_ERROR;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-VOID\r
-SendError (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr\r
-  )\r
-/*++\r
-Routine description:\r
-  Send TFTP ERROR message to TFTP server\r
-\r
-Parameters:\r
-  Private :=\r
-  ServerIpPtr :=\r
-  ServerPortPtr :=\r
-  OurPortPtr :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  struct Tftpv4Error  *ErrStr;\r
-  UINTN               Len;\r
-\r
-  ErrStr            = (VOID *) Private->TftpErrorBuffer;\r
-  Len               = sizeof *ErrStr;\r
-\r
-  ErrStr->OpCode    = HTONS (TFTP_ERROR);\r
-  ErrStr->ErrCode   = HTONS (TFTP_ERR_OPTION);\r
-  ErrStr->ErrMsg[0] = 0;\r
-\r
-  UdpWrite (\r
-    Private,\r
-    EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,\r
-    ServerIpPtr,\r
-    ServerPortPtr,\r
-    0,\r
-    0,\r
-    OurPortPtr,\r
-    0,\r
-    0,\r
-    &Len,\r
-    ErrStr\r
-    );\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-SendAckAndGetData (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_IP_ADDRESS              *ReplyIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr,\r
-  UINT16                      Timeout,\r
-  UINTN                       *ReplyLenPtr,\r
-  UINT8                       *PxeBcMode,\r
-  UINT64                      *BlockNumPtr,\r
-  BOOLEAN                     AckOnly\r
-  )\r
-/*++\r
-Routine description:\r
-  Send TFTP ACK packet to server and read next DATA packet.\r
-\r
-Parameters:\r
-  Private := Pointer to PxeBc interface\r
-  ServerIpPtr := Pointer to TFTP server IP address\r
-  ServerPortPtr := Pointer to TFTP server UDP port\r
-  ReplyIpPtr := Pointer to TFTP DATA packet destination IP address\r
-  OurPortPtr := Pointer to TFTP client UDP port\r
-  Timeout :=\r
-  ReplyLenPtr := Pointer to packet length\r
-  PxeBcMode := Pointer to packet buffer\r
-  BlockNumPtr := Pointer to block number\r
-  AckOnly := TRUE == Send last ack - do not wait for reply\r
-\r
-Returns:\r
---*/\r
-{\r
-  struct Tftpv4Data DataBuffer;\r
-  struct Tftpv4Ack  *Ack2Ptr;\r
-  struct Tftpv4Ack8 *Ack8Ptr;\r
-  EFI_STATUS        Status;\r
-  UINTN             Len;\r
-\r
-  Ack2Ptr = (VOID *) Private->TftpAckBuffer;\r
-  Ack8Ptr = (VOID *) Private->TftpAckBuffer;\r
-\r
-  if (Private->BigBlkNumFlag) {\r
-    Len               = sizeof (struct Tftpv4Ack8);\r
-\r
-    Ack8Ptr->OpCode   = HTONS (TFTP_ACK8);\r
-    Ack8Ptr->BlockNum = Swap64 (*BlockNumPtr);\r
-\r
-    Status = UdpWrite (\r
-              Private,\r
-              EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,\r
-              ServerIpPtr,\r
-              ServerPortPtr,\r
-              0,\r
-              0,\r
-              OurPortPtr,\r
-              0,\r
-              0,\r
-              &Len,\r
-              Ack8Ptr\r
-              );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  } else {\r
-    Len               = sizeof (struct Tftpv4Ack);\r
-\r
-    Ack2Ptr->OpCode   = HTONS (TFTP_ACK);\r
-    Ack2Ptr->BlockNum = HTONS ((UINT16) *BlockNumPtr);\r
-\r
-    Status = UdpWrite (\r
-              Private,\r
-              EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,\r
-              ServerIpPtr,\r
-              ServerPortPtr,\r
-              0,\r
-              0,\r
-              OurPortPtr,\r
-              0,\r
-              0,\r
-              &Len,\r
-              Ack2Ptr\r
-              );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  if (AckOnly) {\r
-    //\r
-    // ACK of last packet.  This is just a courtesy.\r
-    // Do not wait for response.\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
-  //\r
-  // read reply\r
-  //\r
-  Status = TftpUdpRead (\r
-            Private,\r
-            0,\r
-            &DataBuffer,\r
-            ReplyLenPtr,\r
-            PxeBcMode,\r
-            ServerIpPtr,\r
-            ServerPortPtr,\r
-            ReplyIpPtr,\r
-            OurPortPtr,\r
-            Timeout\r
-            );\r
-\r
-  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
-    return Status;\r
-  }\r
-  //\r
-  // got a good reply (so far)\r
-  // check for next data packet\r
-  //\r
-  if (!Private->BigBlkNumFlag && DataBuffer.Header.OpCode == HTONS (TFTP_DATA)) {\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr);\r
-    }\r
-\r
-    *BlockNumPtr = NTOHS (DataBuffer.Header.BlockNum);\r
-    return Status;\r
-  }\r
-\r
-  if (Private->BigBlkNumFlag && DataBuffer.Header.OpCode == HTONS (TFTP_DATA8)) {\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr);\r
-    }\r
-\r
-    *BlockNumPtr = Swap64 (*(UINT64 *) &DataBuffer.Header.BlockNum);\r
-    return Status;\r
-  }\r
-\r
-  return EFI_PROTOCOL_ERROR;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-LockStepReceive (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  UINTN                       PacketSize,\r
-  UINT64                      *BufferSizePtr,\r
-  UINT64                      Offset,\r
-  UINT8                       *BufferPtr,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_IP_ADDRESS              *ReplyIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr,\r
-  UINT64                      LastBlock,\r
-  UINT16                      Timeout,\r
-  IN BOOLEAN                  DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-  Read rest of file after successfull M/TFTP request.\r
-\r
-Parameters:\r
-  Private := Pointer to PxeBc interface\r
-  PacketSize := Pointer to packet size\r
-  BufferSizePtr := Pointer to buffer (file) size\r
-  Offset := Offset into buffer of next packet\r
-  BufferPtr := Pointer to receive buffer\r
-  ServerIpPtr := Pointer to TFTP server IP address\r
-  ServerPortPtr := Pointer to TFTP server UDP port\r
-  ReplyIpPtr := Pointer to TFTP DATA packet destination IP address\r
-  OurPortPtr := Pointer to TFTP client UDP port\r
-  LastBlock := Last block number received\r
-  Timeout :=\r
-  DontUseBuffer := TRUE == throw away data, just count # of bytes\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT64      BlockNum;\r
-  UINT64      BufferSize;\r
-  UINTN       Retries;\r
-  UINTN       SaveLen;\r
-  UINTN       ReplyLen;\r
-\r
-  ReplyLen  = PacketSize;\r
-  BlockNum  = LastBlock;\r
-\r
-  DEBUG ((EFI_D_INFO, "\nLockStepReceive()  PacketSize = %d", PacketSize));\r
-\r
-  if (DontUseBuffer) {\r
-    BufferSize = PacketSize;\r
-  } else {\r
-    BufferSize = *BufferSizePtr - Offset;\r
-    BufferPtr += Offset;\r
-  }\r
-\r
-  while (ReplyLen >= 512 && ReplyLen == PacketSize) {\r
-    if (BufferSize < PacketSize) {\r
-      ReplyLen = (UINTN) ((BufferSize > 0) ? BufferSize : 0);\r
-    }\r
-\r
-    SaveLen = ReplyLen;\r
-\r
-    //\r
-    // write an ack packet and get data - retry up to NUM_ACK_RETRIES on timeout\r
-    //\r
-    Retries = NUM_ACK_RETRIES;\r
-\r
-    do {\r
-      ReplyLen = SaveLen;\r
-\r
-      Status = SendAckAndGetData (\r
-                Private,\r
-                ServerIpPtr,\r
-                ServerPortPtr,\r
-                ReplyIpPtr,\r
-                OurPortPtr,\r
-                Timeout,\r
-                (UINTN *) &ReplyLen,\r
-                BufferPtr,\r
-                &BlockNum,\r
-                FALSE\r
-                );\r
-\r
-      if (!EFI_ERROR (Status) || Status == EFI_BUFFER_TOO_SMALL) {\r
-        if (BlockNum == LastBlock) {\r
-          DEBUG ((EFI_D_NET, "\nresend"));\r
-          //\r
-          // a resend - continue\r
-          //\r
-          Status = EFI_TIMEOUT;\r
-        } else if (Private->BigBlkNumFlag) {\r
-          if (BlockNum != ++LastBlock) {\r
-            DEBUG ((EFI_D_NET, "\nLockStepReceive()  Exit #1a"));\r
-            //\r
-            // not correct blocknum - error\r
-            //\r
-            return EFI_PROTOCOL_ERROR;\r
-          }\r
-        } else {\r
-          LastBlock = (LastBlock + 1) & 0xFFFF;\r
-          if (BlockNum != LastBlock) {\r
-            DEBUG ((EFI_D_NET, "\nLockStepReceive()  Exit #1b"));\r
-            return EFI_PROTOCOL_ERROR;\r
-            //\r
-            // not correct blocknum - error\r
-            //\r
-          }\r
-        }\r
-      }\r
-    } while (Status == EFI_TIMEOUT && --Retries);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      if (Status != EFI_BUFFER_TOO_SMALL) {\r
-        SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr);\r
-      }\r
-\r
-      return Status;\r
-    }\r
-\r
-    if (DontUseBuffer) {\r
-      BufferSize += ReplyLen;\r
-    } else {\r
-      BufferPtr += ReplyLen;\r
-      BufferSize -= ReplyLen;\r
-    }\r
-  }\r
-  //\r
-  // while (ReplyLen == PacketSize);\r
-  //\r
-  if (DontUseBuffer) {\r
-    if (BufferSizePtr != NULL) {\r
-      *BufferSizePtr = (BufferSize - PacketSize);\r
-    }\r
-  } else {\r
-    *BufferSizePtr -= BufferSize;\r
-  }\r
-\r
-  /* Send ACK of last packet. */\r
-  ReplyLen = 0;\r
-\r
-  SendAckAndGetData (\r
-    Private,\r
-    ServerIpPtr,\r
-    ServerPortPtr,\r
-    ReplyIpPtr,\r
-    OurPortPtr,\r
-    Timeout,\r
-    (UINTN *) &ReplyLen,\r
-    BufferPtr,\r
-    &BlockNum,\r
-    TRUE\r
-    );\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-\r
-//\r
-// some literals\r
-//\r
-STATIC UINT8                      Mode[]          = MODE_BINARY;\r
-STATIC UINT8                      BlockSizeOp[]   = OP_BLKSIZE;\r
-STATIC UINT8                      TsizeOp[]       = OP_TFRSIZE;\r
-STATIC UINT8                      OverwriteOp[]   = OP_OVERWRITE;\r
-STATIC UINT8                      BigBlkNumOp[]   = OP_BIGBLKNUM;\r
-STATIC EFI_PXE_BASE_CODE_UDP_PORT TftpRequestPort = TFTP_OPEN_PORT;\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-UINT8 *\r
-FindOption (\r
-  UINT8 *OptionPtr,\r
-  INTN  OpLen,\r
-  UINT8 *OackPtr,\r
-  INTN  OackSize\r
-  )\r
-/*++\r
-Routine description:\r
-  Check TFTP OACK packet for option.\r
-\r
-Parameters:\r
-  OptionPtr := Pointer to option string to find\r
-  OpLen := Length of option string\r
-  OackPtr := Pointer to OACK data\r
-  OackSize := Length of OACK data\r
-\r
-Returns:\r
-  Pointer to value field if option found or NULL if not found.\r
---*/\r
-{\r
-  if ((OackSize -= OpLen) <= 0) {\r
-    return NULL;\r
-  }\r
-\r
-  do {\r
-    if (!CompareMem (OackPtr, OptionPtr, OpLen)) {\r
-      return OackPtr + OpLen;\r
-    }\r
-\r
-    ++OackPtr;\r
-  } while (--OackSize);\r
-\r
-  return NULL;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-#define BKSZOP      1 // block size\r
-#define TSIZEOP     2 // transfer size\r
-#define OVERWRITEOP 4 // overwrite\r
-#define BIGBLKNUMOP 8 // big block numbers\r
-STATIC\r
-EFI_STATUS\r
-TftpRwReq (\r
-  UINT16                      Req,\r
-  UINT16                      Options,\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr,\r
-  UINT8                       *FilenamePtr,\r
-  UINTN                       *PacketSizePtr,\r
-  VOID                        *Buffer\r
-  )\r
-/*++\r
-Routine description:\r
-  Send TFTP RRQ/WRQ packet.\r
-\r
-Parameters:\r
-  Req := Type of request to send\r
-  Options := One or more of the #define values above\r
-  Private := Pointer to PxeBc interface\r
-  ServerIpPtr := Pointer to TFTP server IP address\r
-  ServerPortPtr := Pointer to TFTP server UDP port\r
-  OurPortPtr := Pointer to TFTP client UDP port\r
-  FilenamePtr := Pointer to TFTP file or directory name\r
-  PacketSizePtr := Pointer to block size\r
-  Buffer :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  union {\r
-    UINT8             Data[514];\r
-    struct Tftpv4Req  ReqStr;\r
-  } *u;\r
-\r
-  UINT16  OpFlags;\r
-  INTN    Len;\r
-  INTN    TotalLen;\r
-  UINT8   *Ptr;\r
-\r
-  if (*OurPortPtr == 0) {\r
-    OpFlags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT;\r
-  } else {\r
-    OpFlags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT;\r
-  }\r
-  //\r
-  // build the basic request - opcode, filename, mode\r
-  //\r
-  u                 = Buffer;\r
-  u->ReqStr.OpCode  = HTONS (Req);\r
-  TotalLen = sizeof (Mode) + sizeof (u->ReqStr.OpCode) + (Len = 1 + AsciiStrLen ((CHAR8 *)FilenamePtr));\r
-\r
-  CopyMem (u->ReqStr.FileName, FilenamePtr, Len);\r
-  Ptr = (UINT8 *) (u->ReqStr.FileName + Len);\r
-\r
-  CopyMem (Ptr, Mode, sizeof (Mode));\r
-  Ptr += sizeof (Mode);\r
-\r
-  if (Options & BKSZOP) {\r
-    CopyMem (Ptr, BlockSizeOp, sizeof (BlockSizeOp));\r
-    UtoA10 (*PacketSizePtr, Ptr + sizeof (BlockSizeOp));\r
-\r
-    TotalLen += (Len = 1 + AsciiStrLen ((CHAR8 *)Ptr + sizeof (BlockSizeOp)) + sizeof (BlockSizeOp));\r
-\r
-    Ptr += Len;\r
-  }\r
-\r
-  if (Options & TSIZEOP) {\r
-    CopyMem (Ptr, TsizeOp, sizeof (TsizeOp));\r
-    CopyMem (Ptr + sizeof (TsizeOp), "0", 2);\r
-    TotalLen += sizeof (TsizeOp) + 2;\r
-    Ptr += sizeof (TsizeOp) + 2;\r
-  }\r
-\r
-  if (Options & OVERWRITEOP) {\r
-    CopyMem (Ptr, OverwriteOp, sizeof (OverwriteOp));\r
-    CopyMem (Ptr + sizeof (OverwriteOp), "1", 2);\r
-    TotalLen += sizeof (OverwriteOp) + 2;\r
-    Ptr += sizeof (OverwriteOp) + 2;\r
-  }\r
-\r
-  if (Options & BIGBLKNUMOP) {\r
-    CopyMem (Ptr, BigBlkNumOp, sizeof (BigBlkNumOp));\r
-    CopyMem (Ptr + sizeof (BigBlkNumOp), "8", 2);\r
-    TotalLen += sizeof (BigBlkNumOp) + 2;\r
-    Ptr += sizeof (BigBlkNumOp) + 2;\r
-  }\r
-  //\r
-  // send it\r
-  //\r
-  return UdpWrite (\r
-          Private,\r
-          OpFlags,\r
-          ServerIpPtr,\r
-          ServerPortPtr,\r
-          0,\r
-          0,\r
-          OurPortPtr,\r
-          0,\r
-          0,\r
-          (UINTN *) &TotalLen,\r
-          u\r
-          );\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-TftpRwReqwResp (\r
-  UINT16                      Req,\r
-  UINT16                      Options,\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  VOID                        *HeaderPtr,\r
-  UINTN                       *PacketSizePtr,\r
-  UINTN                       *ReplyLenPtr,\r
-  VOID                        *BufferPtr,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *ServerReplyPortPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  *OurPortPtr,\r
-  UINT8                       *FilenamePtr,\r
-  UINT16                      Timeout\r
-  )\r
-/*++\r
-Routine description:\r
-  Start TFTP session.  Issue request and wait for response.\r
-  Retry three times on error.  If failed using options,\r
-  retry three times w/o options on error.\r
-\r
-Parameters:\r
-  Req := TFTP request type\r
-  Options := TFTP option bits\r
-  Private := Pointer to PxeBc interface\r
-  HeaderPtr :=\r
-  PacketSizePtr := Pointer to block size\r
-  ReplyLenPtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr := Pointer to TFTP server IP address\r
-  ServerPortPtr := Pointer to TFTP server UDP port\r
-  ServerReplyPortPtr :=\r
-  OurPortPtr := Pointer to TFTP client UDP Port\r
-  FilenamePtr := Pointer to file or directory name\r
-  Timeout :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_STATUS  Status;\r
-  UINTN       SaveReplyLen;\r
-  INTN        Retries;\r
-  UINT8       Buffer[514];\r
-\r
-  SaveReplyLen            = *ReplyLenPtr;\r
-  Retries                 = 3;\r
-  Private->BigBlkNumFlag  = FALSE;\r
-  *OurPortPtr             = 0;\r
-  //\r
-  // generate random\r
-  //\r
-  do {\r
-    if (*OurPortPtr != 0) {\r
-      if (++ *OurPortPtr == 0) {\r
-        *OurPortPtr = PXE_RND_PORT_LOW;\r
-      }\r
-    }\r
-    //\r
-    // send request from our Ip = StationIp\r
-    //\r
-    if ((Status = TftpRwReq (\r
-                    Req,\r
-                    Options,\r
-                    Private,\r
-                    ServerIpPtr,\r
-                    ServerPortPtr,\r
-                    OurPortPtr,\r
-                    FilenamePtr,\r
-                    PacketSizePtr,\r
-                    Buffer\r
-                    )) != EFI_SUCCESS) {\r
-      DEBUG (\r
-        (EFI_D_WARN,\r
-        "\nTftpRwReqwResp()  Exit #1  %xh (%r)",\r
-        Status,\r
-        Status)\r
-        );\r
-\r
-      return Status;\r
-    }\r
-    //\r
-    // read reply to our Ip = StationIp\r
-    //\r
-    *ReplyLenPtr = SaveReplyLen;\r
-\r
-    Status = TftpUdpRead (\r
-              Private,\r
-              EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
-              HeaderPtr,\r
-              ReplyLenPtr,\r
-              BufferPtr,\r
-              ServerIpPtr,\r
-              ServerReplyPortPtr,\r
-              0,\r
-              OurPortPtr,\r
-              Timeout\r
-              );\r
-  } while (Status == EFI_TIMEOUT && --Retries);\r
-\r
-  if (!Options || Status != EFI_TFTP_ERROR) {\r
-    DEBUG (\r
-      (EFI_D_WARN,\r
-      "\nTftpRwReqwResp()  Exit #2  %xh (%r)",\r
-      Status,\r
-      Status)\r
-      );\r
-    return Status;\r
-  }\r
-\r
-  Status = TftpRwReqwResp (\r
-            Req,\r
-            0,\r
-            Private,\r
-            HeaderPtr,\r
-            PacketSizePtr,\r
-            ReplyLenPtr,\r
-            BufferPtr,\r
-            ServerIpPtr,\r
-            ServerPortPtr,\r
-            ServerReplyPortPtr,\r
-            OurPortPtr,\r
-            FilenamePtr,\r
-            Timeout\r
-            );\r
-\r
-  DEBUG ((EFI_D_WARN, "\nTftpRwReqwResp()  Exit #3  %xh (%r)", Status, Status));\r
-\r
-  return Status;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-\r
-//\r
-// mtftp listen\r
-// read on mcast ip, cport, from sport, for data packet\r
-// returns success if gets multicast last packet or all up to last block\r
-// if not missing, then finished\r
-//\r
-STATIC\r
-EFI_STATUS\r
-MtftpListen (\r
-  PXE_BASECODE_DEVICE           *Private,\r
-  UINT64                        *BufferSizePtr,\r
-  UINT8                         *BufferPtr,\r
-  EFI_IP_ADDRESS                *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_MTFTP_INFO  *MtftpInfoPtr,\r
-  UINT64                        *StartBlockPtr,\r
-  UINTN                         *NumMissedPtr,\r
-  UINT16                        TransTimeout,\r
-  UINT16                        ListenTimeout,\r
-  UINT64                        FinalBlock,\r
-  IN BOOLEAN                    DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-  Listen for MTFTP traffic and save desired packets.\r
-\r
-Parameters:\r
-  Private := Pointer to PxeBc interface\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr := Pointer to TFTP server IP address\r
-  MtftpInfoPtr := Pointer to MTFTP session information\r
-  StartBlockPtr := IN=first block we are looking for  OUT=first block received\r
-  NumMissedPtr := Number of blocks missed\r
-  TransTimeout :=\r
-  ListenTimeout :=\r
-  FinalBlock :=\r
-  DontUseBuffer := TRUE == throw packets away, just count bytes\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_STATUS        Status;\r
-  struct Tftpv4Ack  Header;\r
-  UINT64            Offset;\r
-  UINT64            BlockNum;\r
-  UINT64            LastBlockNum;\r
-  UINT64            BufferSize;\r
-  UINTN             NumMissed;\r
-  UINTN             PacketSize;\r
-  UINTN             SaveReplyLen;\r
-  UINTN             ReplyLen;\r
-  UINT16            Timeout;\r
-\r
-  LastBlockNum  = *StartBlockPtr;\r
-  Timeout       = ListenTimeout;\r
-  *NumMissedPtr = 0;\r
-  PacketSize    = 0;\r
-  BufferSize    = *BufferSizePtr;\r
-  ReplyLen      = MAX_TFTP_PKT_SIZE;;\r
-\r
-  //\r
-  // receive\r
-  //\r
-  do {\r
-    if ((SaveReplyLen = ReplyLen) > BufferSize) {\r
-      SaveReplyLen = (UINTN) BufferSize;\r
-    }\r
-\r
-    /* %%TBD - add big block number support */\r
-\r
-    //\r
-    // get data - loop on resends\r
-    //\r
-    do {\r
-      ReplyLen = SaveReplyLen;\r
-\r
-      if ((Status = TftpUdpRead (\r
-                      Private,\r
-                      0,\r
-                      &Header,\r
-                      &ReplyLen,\r
-                      BufferPtr,\r
-                      ServerIpPtr,\r
-                      &MtftpInfoPtr->SPort,\r
-                      &MtftpInfoPtr->MCastIp,\r
-                      &MtftpInfoPtr->CPort,\r
-                      Timeout\r
-                      )) != EFI_SUCCESS) {\r
-        return Status;\r
-      }\r
-      //\r
-      // make sure a data packet\r
-      //\r
-      if (Header.OpCode != HTONS (TFTP_DATA)) {\r
-        return EFI_PROTOCOL_ERROR;\r
-      }\r
-    } while ((BlockNum = NTOHS (Header.BlockNum)) == LastBlockNum);\r
-\r
-    //\r
-    // make sure still going up\r
-    //\r
-    if (LastBlockNum > BlockNum) {\r
-      return EFI_PROTOCOL_ERROR;\r
-    }\r
-\r
-    if (BlockNum - LastBlockNum > 0xFFFFFFFF) {\r
-      return EFI_PROTOCOL_ERROR;\r
-    } else {\r
-      NumMissed = (UINTN) (BlockNum - LastBlockNum - 1);\r
-    }\r
-\r
-    LastBlockNum = BlockNum;\r
-\r
-    //\r
-    // if first time through, some reinitialization\r
-    //\r
-    if (!PacketSize) {\r
-      *StartBlockPtr  = BlockNum;\r
-      PacketSize      = ReplyLen;\r
-      Timeout         = TransTimeout;\r
-    } else {\r
-      *NumMissedPtr = (UINT16) (*NumMissedPtr + NumMissed);\r
-    }\r
-    //\r
-    // if missed packets, update start block,\r
-    // etc. and move packet to proper place in buffer\r
-    //\r
-    if (NumMissed) {\r
-      *StartBlockPtr = BlockNum;\r
-      if (!DontUseBuffer) {\r
-        Offset = NumMissed * PacketSize;\r
-        CopyMem (BufferPtr + Offset, BufferPtr, ReplyLen);\r
-        BufferPtr += Offset;\r
-        BufferSize -= Offset;\r
-      }\r
-    }\r
-\r
-    if (!DontUseBuffer) {\r
-      BufferPtr += ReplyLen;\r
-      BufferSize -= ReplyLen;\r
-    }\r
-  } while (ReplyLen == PacketSize && BlockNum != FinalBlock);\r
-\r
-  *BufferSizePtr = BufferSize;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-MtftpOpen (\r
-  PXE_BASECODE_DEVICE                                               * Private,\r
-  UINT64                                                            *BufferSizePtr,\r
-  UINT8                                                             *BufferPtr,\r
-  UINTN                                                             *PacketSizePtr,\r
-  EFI_IP_ADDRESS                                                    * ServerIpPtr,\r
-  UINT8                                                             *FilenamePtr,\r
-  EFI_PXE_BASE_CODE_MTFTP_INFO                                      * MtftpInfoPtr,\r
-  UINT8                                                             *CompletionStatusPtr,\r
-#define GOTUNI 1\r
-#define GOTMULTI 2\r
-  IN BOOLEAN                    DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-  Open MTFTP session.\r
-\r
-Parameters:\r
-  Private := Pointer to PxeBc interface\r
-  BufferSizePtr := IN=buffer size  OUT=transfer size\r
-  BufferPtr :=\r
-  PacketSizePtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  MtftpInfoPtr :=\r
-  CompletionStatusPtr :=\r
-  DontUseBuffer :=\r
-\r
-Returns:\r
-// mtftp open session\r
-// return code EFI_SUCCESS\r
-//      and *CompletionStatusPtr = GOTUNI | GOTMULTI means done\r
-//      and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest\r
-//      and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all\r
-//      (do not get = GOTUNI - returns NO_DATA go will go to TFTP session)\r
---*/\r
-{\r
-  EFI_STATUS        Status;\r
-  EFI_IP_ADDRESS    OurReplyIp;\r
-  struct Tftpv4Ack  Header;\r
-  INTN              ReplyLen;\r
-  INTN              Retries;\r
-  UINT8             *BufferPtr2;\r
-  UINT8             TmpBuf[514];\r
-\r
-  Retries         = NUM_MTFTP_OPEN_RETRIES;\r
-  BufferPtr2      = BufferPtr;\r
-  *PacketSizePtr  = (UINTN) (EFI_MIN (*BufferSizePtr, MAX_TFTP_PKT_SIZE));\r
-\r
-  do {\r
-    //\r
-    // send a read request\r
-    //\r
-    *CompletionStatusPtr = 0;\r
-\r
-    if ((Status = TftpRwReq (\r
-                    TFTP_RRQ,\r
-                    0,\r
-                    Private,\r
-                    ServerIpPtr,\r
-                    &MtftpInfoPtr->SPort,\r
-                    &MtftpInfoPtr->CPort,\r
-                    FilenamePtr,\r
-                    PacketSizePtr,\r
-                    TmpBuf\r
-                    )) != EFI_SUCCESS) {\r
-      return Status;\r
-    }\r
-\r
-    for (;;) {\r
-      //\r
-      // read reply\r
-      //\r
-      ZeroMem (&OurReplyIp, Private->IpLength);\r
-      ReplyLen = *PacketSizePtr;\r
-\r
-      if ((Status = TftpUdpRead (\r
-                      Private,\r
-                      EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER,\r
-                      &Header,\r
-                      (UINTN *) &ReplyLen,\r
-                      BufferPtr2,\r
-                      ServerIpPtr,\r
-                      &MtftpInfoPtr->SPort,\r
-                      &OurReplyIp,\r
-                      &MtftpInfoPtr->CPort,\r
-                      MtftpInfoPtr->TransmitTimeout\r
-                      )) == EFI_SUCCESS) {\r
-        //\r
-        // check for first data packet\r
-        //\r
-        if (Header.OpCode != HTONS (TFTP_DATA)) {\r
-          return EFI_PROTOCOL_ERROR;\r
-        }\r
-        //\r
-        // check block num\r
-        //\r
-        if (Header.BlockNum != HTONS (1)) {\r
-          //\r
-          // it's not first\r
-          // if we are not the primary client,\r
-          // we probably got first and now second\r
-          // multicast but no unicast, so\r
-          // *CompletionStatusPtr = GOTMULTI - if this is\r
-          // the second, can just go on to listen\r
-          // starting with 2 as the last block\r
-          // received\r
-          //\r
-          if (Header.BlockNum != HTONS (2)) {\r
-            //\r
-            // not second\r
-            //\r
-            *CompletionStatusPtr = 0;\r
-          }\r
-\r
-          return Status;\r
-        }\r
-\r
-        //\r
-        // now actual\r
-        //\r
-        *PacketSizePtr = ReplyLen;\r
-        //\r
-        // see if a unicast data packet\r
-        //\r
-        if (!CompareMem (\r
-              &OurReplyIp,\r
-              &Private->EfiBc.Mode->StationIp,\r
-              Private->IpLength\r
-              )) {\r
-          *CompletionStatusPtr |= GOTUNI;\r
-          //\r
-          // it is\r
-          // if already got multicast packet,\r
-          // got em both\r
-          //\r
-          if (*CompletionStatusPtr & GOTMULTI) {\r
-            break;\r
-          }\r
-        } else if (!CompareMem (\r
-                    &OurReplyIp,\r
-                    &MtftpInfoPtr->MCastIp,\r
-                    Private->IpLength\r
-                    )) {\r
-          //\r
-          // otherwise see if a multicast data packet\r
-          //\r
-          *CompletionStatusPtr |= GOTMULTI;\r
-          //\r
-          // it is\r
-          // got first - bump pointer so that if\r
-          // second multi comes along, we're OK\r
-          //\r
-          if (!DontUseBuffer) {\r
-            BufferPtr2 = (UINT8 *) BufferPtr + ReplyLen;\r
-          }\r
-          //\r
-          // if already got unicast packet,\r
-          // got em both\r
-          //\r
-          if (*CompletionStatusPtr & GOTUNI) {\r
-            break;\r
-          }\r
-        } else {\r
-          //\r
-          // else protocol error\r
-          //\r
-          return EFI_PROTOCOL_ERROR;\r
-        }\r
-      } else if (Status == EFI_TIMEOUT) {\r
-        //\r
-        // bad return code - if timed out, retry\r
-        //\r
-        break;\r
-      } else {\r
-        //\r
-        // else just bad - failed MTFTP open\r
-        //\r
-        return Status;\r
-      }\r
-    }\r
-  } while (Status == EFI_TIMEOUT && --Retries);\r
-\r
-  if (Status != EFI_SUCCESS) {\r
-    //\r
-    // open failed\r
-    //\r
-    return Status;\r
-  }\r
-  //\r
-  // got em both - go into receive mode\r
-  // routine to read rest of file after a successful open (TFTP or MTFTP)\r
-  // sends ACK and gets next data packet until short packet arrives,\r
-  // then sends ACK and (hopefully) times out\r
-  //\r
-  return LockStepReceive (\r
-          Private,\r
-          (UINT16) ReplyLen,\r
-          BufferSizePtr,\r
-          ReplyLen,\r
-          BufferPtr,\r
-          ServerIpPtr,\r
-          &MtftpInfoPtr->SPort,\r
-          &MtftpInfoPtr->MCastIp,\r
-          &MtftpInfoPtr->CPort,\r
-          1,\r
-          MtftpInfoPtr->TransmitTimeout,\r
-          DontUseBuffer\r
-          );\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-MtftpDownload (\r
-  PXE_BASECODE_DEVICE           *Private,\r
-  UINT64                        *BufferSizePtr,\r
-  UINT8                         *BufferPtr,\r
-  EFI_IP_ADDRESS                *ServerIpPtr,\r
-  UINT8                         *FilenamePtr,\r
-  EFI_PXE_BASE_CODE_MTFTP_INFO  *MtftpInfoPtr,\r
-  IN BOOLEAN                    DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-// mtftp\r
-// loop\r
-//  listen\r
-//  if did not get any packets, try MTFTP open\r
-//  if got all packets, return\r
-//  compute listen timeout and loop\r
-\r
-Parameters:\r
-  Private := Pointer to PxeBc interface\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  MtftpInfoPtr :=\r
-  DontUseBuffer :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
-  EFI_STATUS                  Status;\r
-  UINT64                      StartBlock;\r
-  UINT64                      LastBlock;\r
-  UINT64                      LastStartBlock;\r
-  UINT64                      BufferSize;\r
-  UINTN                       Offset;\r
-  UINTN                       NumMissed;\r
-  UINT16                      TransTimeout;\r
-  UINT16                      ListenTimeout;\r
-  UINT8                       *BufferPtrLocal;\r
-\r
-  TransTimeout      = MtftpInfoPtr->TransmitTimeout;\r
-  ListenTimeout     = MtftpInfoPtr->ListenTimeout;\r
-  LastBlock         = 0;\r
-  LastStartBlock    = 0;\r
-  Offset            = 0;\r
-\r
-  Filter.Filters    = EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST;\r
-  Filter.IpCnt      = 2;\r
-  CopyMem (&Filter.IpList[0], &Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS));\r
-  CopyMem (&Filter.IpList[1], &MtftpInfoPtr->MCastIp, sizeof (EFI_IP_ADDRESS));\r
-\r
-  if ((Status = IpFilter (Private, &Filter)) != EFI_SUCCESS) {\r
-    return Status;\r
-  }\r
-\r
-  for (;;) {\r
-    StartBlock  = LastStartBlock;\r
-    BufferSize  = *BufferSizePtr - Offset;\r
-\r
-    if (DontUseBuffer) {\r
-    //\r
-    // overwrie the temp buf\r
-    //\r
-      BufferPtrLocal = BufferPtr;\r
-    } else {\r
-      BufferPtrLocal = BufferPtr + Offset;\r
-\r
-    }\r
-\r
-    if (((Status = MtftpListen (\r
-                      Private,\r
-                      &BufferSize,\r
-                      BufferPtrLocal,\r
-                      ServerIpPtr,\r
-                      MtftpInfoPtr,\r
-                      &StartBlock,\r
-                      &NumMissed,\r
-                      TransTimeout,\r
-                      ListenTimeout,\r
-                      LastBlock,\r
-                      DontUseBuffer\r
-                      )) != EFI_SUCCESS) && (Status != EFI_TIMEOUT)) {\r
-      return Status;\r
-      //\r
-      // failed\r
-      //\r
-    }\r
-    //\r
-    // if none were received, start block is not reset\r
-    //\r
-    if (StartBlock == LastStartBlock) {\r
-      UINT8 CompStat;\r
-\r
-      //\r
-      // timed out with none received - try MTFTP open\r
-      //\r
-      if ((Status = MtftpOpen (\r
-                      Private,\r
-                      BufferSizePtr,\r
-                      BufferPtr,\r
-                      &Offset,\r
-                      ServerIpPtr,\r
-                      FilenamePtr,\r
-                      MtftpInfoPtr,\r
-                      &CompStat,\r
-                      DontUseBuffer\r
-                      )) != EFI_SUCCESS) {\r
-        //\r
-        // open failure - try TFTP\r
-        //\r
-        return Status;\r
-      }\r
-      //\r
-      // return code EFI_SUCCESS\r
-      // and *CompletionStatusPtr = GOTUNI | GOTMULTI means done\r
-      // and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest\r
-      // and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all\r
-      // (do not get = GOTUNI - returns NO_DATA go will go to TFTP session)\r
-      //\r
-      if (CompStat == (GOTUNI | GOTMULTI)) {\r
-      //\r
-      // finished - got it all\r
-      //\r
-        return Status;\r
-      }\r
-\r
-      if (CompStat) {\r
-        //\r
-        // offset is two packet lengths\r
-        //\r
-        Offset <<= 1;\r
-        //\r
-        // last block received\r
-        //\r
-        LastStartBlock = 2;\r
-      } else {\r
-        Offset          = 0;\r
-        LastStartBlock  = 0;\r
-      }\r
-\r
-      ListenTimeout = TransTimeout;\r
-      continue;\r
-    }\r
-    //\r
-    // did we get the last block\r
-    //\r
-    if (Status == EFI_SUCCESS) {\r
-      //\r
-      // yes - set the file size if this was first time\r
-      //\r
-      if (!LastBlock) {\r
-        *BufferSizePtr -= BufferSize;\r
-      }\r
-      //\r
-      // if buffer was too small, finished\r
-      //\r
-      if (!DontUseBuffer) {\r
-        return EFI_BUFFER_TOO_SMALL;\r
-      }\r
-      //\r
-      // if we got them all, finished\r
-      //\r
-      if (!NumMissed && StartBlock == LastStartBlock + 1) {\r
-        return Status;\r
-      }\r
-      //\r
-      // did not get them all - set last block\r
-      //\r
-      LastBlock = (UINT16) (StartBlock - 1);\r
-    }\r
-    //\r
-    // compute listen timeout\r
-    //\r
-    ListenTimeout = (UINT16) ((NumMissed > MtftpInfoPtr->ListenTimeout) ? 0 : (MtftpInfoPtr->ListenTimeout - NumMissed));\r
-\r
-    //\r
-    // reset\r
-    //\r
-    Offset          = 0;\r
-    LastStartBlock  = 0;\r
-  }\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-TftpInfo (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  UINT64                      *BufferSizePtr,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  SrvPort,\r
-  UINT8                       *FilenamePtr,\r
-  UINTN                       *PacketSizePtr\r
-  )\r
-/*++\r
-Routine description:\r
-// TFTP info request routine\r
-// send read request with block size and transfer size options\r
-// get reply\r
-// send error to terminate session\r
-// if OACK received, set info\r
-\r
-Parameters:\r
-  Private :=\r
-  BufferSizePtr :=\r
-  ServerIpPtr :=\r
-  SrvPort :=\r
-  FilenamePtr :=\r
-  PacketSizePtr :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_UDP_PORT  OurPort;\r
-  EFI_PXE_BASE_CODE_UDP_PORT  ServerReplyPort;\r
-  EFI_STATUS                  Status;\r
-  UINT64                      BlockNum;\r
-  UINTN                       Offset;\r
-  UINTN                       ReplyLen;\r
-  UINT8                       *Ptr;\r
-\r
-  union {\r
-    struct Tftpv4Oack OAck2Ptr;\r
-    struct Tftpv4Ack  Ack2Ptr;\r
-    struct Tftpv4Data Datastr;\r
-  } u;\r
-\r
-  OurPort         = 0;\r
-  ServerReplyPort = 0;\r
-  ReplyLen        = sizeof (u.Datastr.Data);\r
-\r
-  //\r
-  // send a write request with the blocksize option -\r
-  // sets our IP and port - and receive reply - sets his port\r
-  // will retry operation up to 3 times if no response,\r
-  // and will retry without options on an error reply\r
-  //\r
-  if ((Status = TftpRwReqwResp (\r
-                  TFTP_RRQ,\r
-                  /* BIGBLKNUMOP | */BKSZOP | TSIZEOP,\r
-                  Private,\r
-                  &u,\r
-                  PacketSizePtr,\r
-                  &ReplyLen,\r
-                  u.Datastr.Data,\r
-                  ServerIpPtr,\r
-                  &SrvPort,\r
-                  &ServerReplyPort,\r
-                  &OurPort,\r
-                  FilenamePtr,\r
-                  REQ_RESP_TIMEOUT\r
-                  )) != EFI_SUCCESS) {\r
-    DEBUG ((EFI_D_WARN, "\nTftpInfo()  Exit #1"));\r
-    return Status;\r
-  }\r
-  //\r
-  // check for good OACK\r
-  //\r
-  if (u.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) {\r
-    //\r
-    // now parse it for options\r
-    // bigblk#\r
-    //\r
-    Ptr = FindOption (\r
-            BigBlkNumOp,\r
-            sizeof (BigBlkNumOp),\r
-            u.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen + sizeof (u.Ack2Ptr.BlockNum)\r
-            );\r
-\r
-    if (Ptr != NULL) {\r
-      if (AtoU (Ptr) == 8) {\r
-        Private->BigBlkNumFlag = TRUE;\r
-      } else {\r
-        return EFI_PROTOCOL_ERROR;\r
-      }\r
-    }\r
-    //\r
-    // blksize\r
-    //\r
-    Ptr = FindOption (\r
-            BlockSizeOp,\r
-            sizeof (BlockSizeOp),\r
-            u.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen += sizeof (u.Ack2Ptr.BlockNum)\r
-            );\r
-\r
-    *PacketSizePtr = (Ptr) ? AtoU (Ptr) : 512;\r
-\r
-    //\r
-    // tsize\r
-    //\r
-    Ptr = FindOption (\r
-            TsizeOp,\r
-            sizeof (TsizeOp),\r
-            u.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen\r
-            );\r
-\r
-    if (Ptr != NULL) {\r
-      *BufferSizePtr = AtoU64 (Ptr);\r
-\r
-      //\r
-      // teminate session with error\r
-      //\r
-      SendError (Private, ServerIpPtr, &ServerReplyPort, &OurPort);\r
-\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    Offset    = 0;\r
-    BlockNum  = 0;\r
-  } else {\r
-    //\r
-    // if MTFTP get filesize, return unsupported\r
-    //\r
-    if (SrvPort != TftpRequestPort) {\r
-      SendError (Private, ServerIpPtr, &ServerReplyPort, &OurPort);\r
-      DEBUG ((EFI_D_WARN, "\nTftpInfo()  Exit #3"));\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-\r
-    Offset    = ReplyLen;\r
-    //\r
-    // last block received\r
-    //\r
-    BlockNum  = 1;\r
-  }\r
-  //\r
-  // does not support the option - do a download with no buffer\r
-  //\r
-  *BufferSizePtr = 0;\r
-\r
-  Status = LockStepReceive (\r
-            Private,\r
-            (UINT16) ReplyLen,\r
-            BufferSizePtr,\r
-            Offset,\r
-            (UINT8 *) &u,\r
-            ServerIpPtr,\r
-            &ServerReplyPort,\r
-            &Private->EfiBc.Mode->StationIp,\r
-            &OurPort,\r
-            BlockNum,\r
-            ACK_TIMEOUT,\r
-            TRUE\r
-            );\r
-\r
-  if (Status != EFI_SUCCESS) {\r
-    DEBUG ((EFI_D_WARN, "\nTftpInfo()  LockStepReceive() == %Xh", Status));\r
-  }\r
-\r
-  if (Status != EFI_BUFFER_TOO_SMALL) {\r
-    return Status;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-TftpDownload (\r
-  PXE_BASECODE_DEVICE         *Private,\r
-  UINT64                      *BufferSizePtr,\r
-  UINT8                       *BufferPtr,\r
-  EFI_IP_ADDRESS              *ServerIpPtr,\r
-  UINT8                       *FilenamePtr,\r
-  UINTN                       *PacketSizePtr,\r
-  EFI_PXE_BASE_CODE_UDP_PORT  SrvPort,\r
-  UINT16                      Req,\r
-  IN BOOLEAN                  DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-// tftp read session\r
-// send read request\r
-// [get OACK\r
-//  send ACK]\r
-// loop\r
-//  get data\r
-//  send ACK\r
-//  while data size is max\r
-\r
-Parameters:\r
-  Private :=\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  PacketSizePtr :=\r
-  SrvPort :=\r
-  Req :=\r
-  DontUseBuffer :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_UDP_PORT  OurPort;\r
-  EFI_PXE_BASE_CODE_UDP_PORT  ServerReplyPort;\r
-  EFI_STATUS                  Status;\r
-  UINT64                      Offset;\r
-  UINT64                      BlockNum;\r
-  UINTN                       ReplyLen;\r
-  UINT8                       *Ptr;\r
-\r
-  union {\r
-    struct Tftpv4Ack    Ack2Ptr;\r
-    struct Tftpv4Oack   OAck2Ptr;\r
-    struct Tftpv4Data   Data;\r
-    struct Tftpv4Ack8   Ack8Ptr;\r
-    struct Tftpv4Data8  Data8;\r
-  } U;\r
-\r
-  OurPort         = 0;\r
-  ServerReplyPort = 0;\r
-  ReplyLen        = (UINTN) ((*BufferSizePtr > 0xFFFF) ? 0xFFFF : *BufferSizePtr);\r
-\r
-  //\r
-  // send a read request with the blocksize option - sets our IP and port\r
-  // - and receive reply - sets his port will retry operation up to 3\r
-  // times if no response, and will retry without options on an error\r
-  // reply\r
-  //\r
-  if ((Status = TftpRwReqwResp (\r
-                  Req,\r
-                  /* BIGBLKNUMOP | */BKSZOP,\r
-                  Private,\r
-                  &U,\r
-                  PacketSizePtr,\r
-                  &ReplyLen,\r
-                  BufferPtr,\r
-                  ServerIpPtr,\r
-                  &SrvPort,\r
-                  &ServerReplyPort,\r
-                  &OurPort,\r
-                  FilenamePtr,\r
-                  REQ_RESP_TIMEOUT\r
-                  )) != EFI_SUCCESS) {\r
-    DEBUG ((EFI_D_WARN, "\nTftpDownload()  Exit #1  %xh (%r)", Status, Status));\r
-    return Status;\r
-  }\r
-  //\r
-  // check for OACK\r
-  //\r
-  if (U.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) {\r
-    //\r
-    // get the OACK\r
-    //\r
-    CopyMem (U.Data.Data, BufferPtr, ReplyLen);\r
-\r
-    Ptr = FindOption (\r
-            BigBlkNumOp,\r
-            sizeof (BigBlkNumOp),\r
-            U.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen + sizeof (U.Ack2Ptr.BlockNum)\r
-            );\r
-\r
-    if (Ptr != NULL) {\r
-      if (AtoU (Ptr) == 8) {\r
-        Private->BigBlkNumFlag = TRUE;\r
-      } else {\r
-        return EFI_PROTOCOL_ERROR;\r
-      }\r
-    }\r
-    //\r
-    // now parse it for blocksize option\r
-    //\r
-    Ptr = FindOption (\r
-            BlockSizeOp,\r
-            sizeof (BlockSizeOp),\r
-            U.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen += sizeof (U.Ack2Ptr.BlockNum)\r
-            );\r
-\r
-    ReplyLen  = (Ptr != NULL) ? AtoU (Ptr) : 512;\r
-\r
-    Offset    = 0;\r
-    //\r
-    // last block received\r
-    //\r
-    BlockNum  = 0;\r
-  } else if (U.Ack2Ptr.OpCode != HTONS (TFTP_DATA) || U.Ack2Ptr.BlockNum != HTONS (1)) {\r
-    //\r
-    // or data\r
-    //\r
-    DEBUG ((EFI_D_WARN, "\nTftpDownload()  Exit #2  %xh (%r)", Status, Status));\r
-\r
-    return EFI_PROTOCOL_ERROR;\r
-  } else {\r
-    //\r
-    // got good data packet\r
-    //\r
-    Offset    = ReplyLen;\r
-    //\r
-    // last block received\r
-    //\r
-    BlockNum  = 1;\r
-  }\r
-\r
-  if (PacketSizePtr != NULL) {\r
-    *PacketSizePtr = ReplyLen;\r
-  }\r
-  //\r
-  // routine to read rest of file after a successful open (TFTP or MTFTP)\r
-  // sends ACK and gets next data packet until short packet arrives, then sends\r
-  // ACK and (hopefully) times out\r
-  // if first packet has been read, BufferPtr and BufferSize must reflect fact\r
-  //\r
-  Status = LockStepReceive (\r
-            Private,\r
-            ReplyLen,\r
-            BufferSizePtr,\r
-            Offset,\r
-            BufferPtr,\r
-            ServerIpPtr,\r
-            &ServerReplyPort,\r
-            &Private->EfiBc.Mode->StationIp,\r
-            &OurPort,\r
-            BlockNum,\r
-            ACK_TIMEOUT,\r
-            DontUseBuffer\r
-            );\r
-\r
-  if (Status != EFI_SUCCESS) {\r
-    DEBUG ((EFI_D_WARN, "\nTftpDownload()  Exit #3  %xh (%r)", Status, Status));\r
-\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      Status = TftpInfo (\r
-                Private,\r
-                BufferSizePtr,\r
-                ServerIpPtr,\r
-                SrvPort,\r
-                FilenamePtr,\r
-                PacketSizePtr\r
-                );\r
-\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = EFI_BUFFER_TOO_SMALL;\r
-      }\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-TftpUpload (\r
-  PXE_BASECODE_DEVICE *Private,\r
-  UINT64              *BufferSizePtr,\r
-  VOID                *BufferPtr,\r
-  EFI_IP_ADDRESS      *ServerIpPtr,\r
-  UINT8               *FilenamePtr,\r
-  UINTN               *PacketSizePtr,\r
-  BOOLEAN             Overwrite\r
-  )\r
-/*++\r
-Routine description:\r
-// tftp write session\r
-// send write request\r
-// get OACK or ACK\r
-// loop\r
-//  send min (rest of data, max data packet)\r
-//  get ACK\r
-//  while data size is max\r
-\r
-Parameters:\r
-  Private :=\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  PacketSizePtr :=\r
-  Overwrite :=\r
-\r
-Returns:\r
---*/\r
-{\r
-  struct Tftpv4Ack            Header;\r
-  EFI_PXE_BASE_CODE_UDP_PORT  OurPort;\r
-  EFI_PXE_BASE_CODE_UDP_PORT  ServerReplyPort;\r
-  EFI_STATUS                  Status;\r
-  UINT64                      BlockNum;\r
-  UINT64                      TransferSize;\r
-  UINTN                       ReplyLen;\r
-  UINTN                       TransferLen;\r
-  UINT16                      Options;\r
-  UINT8                       *Ptr;\r
-\r
-  union {\r
-    struct Tftpv4Oack OAck2Ptr;\r
-    struct Tftpv4Ack  Ack2Ptr;\r
-    struct Tftpv4Data Datastr;\r
-  } u;\r
-\r
-  OurPort         = 0;\r
-  ServerReplyPort = 0;\r
-  TransferSize    = *BufferSizePtr;\r
-  ReplyLen        = sizeof (u.Datastr.Data);\r
-  Options         = (UINT16) ((Overwrite) ? OVERWRITEOP | BKSZOP : BKSZOP);\r
-\r
-  //\r
-  // send a write request with the blocksize option - sets our IP and port -\r
-  // and receive reply - sets his port\r
-  // will retry operation up to 3 times if no response, and will retry without\r
-  // options on an error reply\r
-  //\r
-  if ((Status = TftpRwReqwResp (\r
-                  TFTP_WRQ,\r
-                  Options,\r
-                  Private,\r
-                  &u,\r
-                  PacketSizePtr,\r
-                  &ReplyLen,\r
-                  u.Datastr.Data,\r
-                  ServerIpPtr,\r
-                  &TftpRequestPort,\r
-                  &ServerReplyPort,\r
-                  &OurPort,\r
-                  FilenamePtr,\r
-                  REQ_RESP_TIMEOUT\r
-                  )) != EFI_SUCCESS) {\r
-    return Status;\r
-  }\r
-  //\r
-  // check for OACK\r
-  //\r
-  if (u.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) {\r
-    //\r
-    // parse it for blocksize option\r
-    //\r
-    Ptr = FindOption (\r
-            BlockSizeOp,\r
-            sizeof (BlockSizeOp),\r
-            u.OAck2Ptr.OpAck[0].Option,\r
-            ReplyLen += sizeof (u.Ack2Ptr.BlockNum)\r
-            );\r
-    *PacketSizePtr = (Ptr) ? AtoU (Ptr) : 512;\r
-  }\r
-  //\r
-  // or ACK\r
-  //\r
-  else if (u.Ack2Ptr.OpCode == HTONS (TFTP_ACK)) {\r
-    //\r
-    // option was not supported\r
-    //\r
-    *PacketSizePtr = 512;\r
-  } else {\r
-    return EFI_PROTOCOL_ERROR;\r
-  }\r
-  //\r
-  // loop\r
-  //\r
-  Header.OpCode   = HTONS (TFTP_DATA);\r
-  BlockNum        = 1;\r
-  Header.BlockNum = HTONS (1);\r
-\r
-  do {\r
-    UINTN HeaderSize;\r
-    INTN  Retries;\r
-\r
-    Retries     = NUM_ACK_RETRIES;\r
-    HeaderSize  = sizeof (Header);\r
-    TransferLen = (UINTN) (EFI_MIN (*PacketSizePtr, TransferSize));\r
-\r
-    //\r
-    // write a data packet and get an ack\r
-    //\r
-    do {\r
-      //\r
-      // write\r
-      //\r
-      if ((Status = UdpWrite (\r
-                      Private,\r
-                      EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,\r
-                      ServerIpPtr,\r
-                      &ServerReplyPort,\r
-                      0,\r
-                      0,\r
-                      &OurPort,\r
-                      &HeaderSize,\r
-                      &Header,\r
-                      &TransferLen,\r
-                      BufferPtr\r
-                      )) != EFI_SUCCESS) {\r
-        return Status;\r
-      }\r
-      //\r
-      // read reply\r
-      //\r
-      ReplyLen = sizeof (u.Datastr.Data);\r
-\r
-      if ((Status = TftpUdpRead (\r
-                      Private,\r
-                      0,\r
-                      &u,\r
-                      &ReplyLen,\r
-                      u.Datastr.Data,\r
-                      ServerIpPtr,\r
-                      &ServerReplyPort,\r
-                      0,\r
-                      &OurPort,\r
-                      ACK_TIMEOUT\r
-                      )) == EFI_SUCCESS) {\r
-        //\r
-        // check for ACK for this data packet\r
-        //\r
-        if (u.Ack2Ptr.OpCode != HTONS (TFTP_ACK)) {\r
-          return EFI_PROTOCOL_ERROR;\r
-        }\r
-\r
-        if (u.Ack2Ptr.BlockNum != Header.BlockNum) {\r
-          //\r
-          // not for this packet - continue\r
-          //\r
-          Status = EFI_TIMEOUT;\r
-        }\r
-      }\r
-    } while (Status == EFI_TIMEOUT && --Retries);\r
-\r
-    if (Status != EFI_SUCCESS) {\r
-      return Status;\r
-    }\r
-\r
-    BufferPtr = (VOID *) ((UINT8 *) (BufferPtr) + TransferLen);\r
-    TransferSize -= TransferLen;\r
-    ++BlockNum;\r
-    Header.BlockNum = HTONS ((UINT16) BlockNum);\r
-  } while (TransferLen == *PacketSizePtr);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-PxeBcMtftp (\r
-  PXE_BASECODE_DEVICE               *Private,\r
-  IN EFI_PXE_BASE_CODE_TFTP_OPCODE  Operation,\r
-  UINT64                            *BufferSizePtr,\r
-  VOID                              *BufferPtr,\r
-  EFI_IP_ADDRESS                    *ServerIpPtr,\r
-  UINT8                             *FilenamePtr,\r
-  UINTN                             *PacketSizePtr,\r
-  IN EFI_PXE_BASE_CODE_MTFTP_INFO   *MtftpInfoPtr, OPTIONAL\r
-  IN BOOLEAN                        Overwrite,\r
-  IN BOOLEAN                        DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-  MTFTP API entry point\r
-\r
-Parameters:\r
-  Private :=\r
-  Operation :=\r
-  BufferSizePtr :=\r
-  BufferPtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  PacketSizePtr :=\r
-  MtftpInfoPtr :=\r
-  Overwrite :=\r
-  DontUseBuffer :=\r
-\r
-Returns:\r
- *  EFI_INVALID_PARAMETER\r
- *  EFI_OUT_OF_RESOURCES\r
- *  EFI_BAD_BUFFER_SIZE\r
- *  Status is also returned from IpFilter(), TftpInfo(), MtftpDownload(),\r
- *  TftpDownload() and TftpUpload().\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
-  EFI_STATUS                  StatCode;\r
-  UINT64                      BufferSizeLocal;\r
-  UINTN                       PacketSize;\r
-  UINT8                       *BufferPtrLocal;\r
-\r
-  Filter.Filters  = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
-  Filter.IpCnt    = 0;\r
-  Filter.reserved = 0;\r
-\r
-  /* No error has occurred, yet. */\r
-  Private->EfiBc.Mode->TftpErrorReceived = FALSE;\r
-\r
-  /* We must at least have an MTFTP server IP address and\r
-   * a pointer to the buffer size.\r
-   */\r
-  if (!ServerIpPtr || !BufferSizePtr) {\r
-    DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #1"));\r
-\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Private->Function = EFI_PXE_BASE_CODE_FUNCTION_MTFTP;\r
-\r
-  //\r
-  // make sure filter set to unicast at start\r
-  //\r
-  if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {\r
-    DEBUG (\r
-      (EFI_D_NET,\r
-      "\nPxeBcMtftp()  Exit  IpFilter() == %Xh",\r
-      StatCode)\r
-      );\r
-\r
-    return StatCode;\r
-  }\r
-  //\r
-  // set unset parms to default values\r
-  //\r
-  if (!PacketSizePtr) {\r
-    *(PacketSizePtr = &PacketSize) = MAX_TFTP_PKT_SIZE;\r
-  }\r
-\r
-  if (*PacketSizePtr > *BufferSizePtr) {\r
-    *PacketSizePtr = (UINTN) *BufferSizePtr;\r
-  }\r
-\r
-  if (*PacketSizePtr < MIN_TFTP_PKT_SIZE) {\r
-    *PacketSizePtr = MIN_TFTP_PKT_SIZE;\r
-  }\r
-\r
-  if (*PacketSizePtr > BUFFER_ALLOCATE_SIZE) {\r
-    *PacketSizePtr = BUFFER_ALLOCATE_SIZE;\r
-  }\r
-\r
-  if (*PacketSizePtr > MAX_TFTP_PKT_SIZE) {\r
-    *PacketSizePtr = MAX_TFTP_PKT_SIZE;\r
-  }\r
-\r
-  if (Operation == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE) {\r
-    StatCode = TftpInfo (\r
-                Private,\r
-                BufferSizePtr,\r
-                ServerIpPtr,\r
-                TftpRequestPort,\r
-                FilenamePtr,\r
-                PacketSizePtr\r
-                );\r
-\r
-    if (StatCode != EFI_SUCCESS) {\r
-      DEBUG (\r
-        (EFI_D_WARN,\r
-        "\nPxeBcMtftp()  Exit  TftpInfo() == %Xh",\r
-        StatCode)\r
-        );\r
-    }\r
-\r
-    return StatCode;\r
-  }\r
-\r
-  if (Operation == EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE) {\r
-    if (!MtftpInfoPtr || !MtftpInfoPtr->SPort) {\r
-      DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #2"));\r
-      return EFI_INVALID_PARAMETER;\r
-    } else {\r
-      StatCode = TftpInfo (\r
-                  Private,\r
-                  BufferSizePtr,\r
-                  ServerIpPtr,\r
-                  MtftpInfoPtr->SPort,\r
-                  FilenamePtr,\r
-                  PacketSizePtr\r
-                  );\r
-\r
-      gBS->Stall (10000);\r
-\r
-      if (StatCode != EFI_SUCCESS) {\r
-        DEBUG (\r
-          (EFI_D_WARN,\r
-          "\nPxeBcMtftp()  Exit  TftpInfo() == %Xh",\r
-          StatCode)\r
-          );\r
-      }\r
-\r
-      return StatCode;\r
-    }\r
-  }\r
-\r
-  if (!BufferPtr && !DontUseBuffer) {\r
-    //\r
-    // if dontusebuffer is false and no buffer???\r
-    //\r
-    DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #3"));\r
-    //\r
-    // DontUseBuffer can be true only for read_file operation\r
-    //\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DontUseBuffer) {\r
-    BufferPtrLocal = AllocatePool (BUFFER_ALLOCATE_SIZE);\r
-    if (BufferPtrLocal == NULL) {\r
-      DEBUG ((EFI_D_NET, "\nPxeBcMtftp()  Exit #4"));\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    BufferSizeLocal = BUFFER_ALLOCATE_SIZE;\r
-  } else {\r
-    if (!*BufferSizePtr && Operation != EFI_PXE_BASE_CODE_TFTP_WRITE_FILE) {\r
-      DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #5"));\r
-      return EFI_BAD_BUFFER_SIZE;\r
-    }\r
-\r
-    BufferPtrLocal  = BufferPtr;\r
-    BufferSizeLocal = *BufferSizePtr;\r
-  }\r
-\r
-  switch (Operation) {\r
-  case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:\r
-    if (FilenamePtr == NULL ||\r
-        MtftpInfoPtr == NULL ||\r
-        MtftpInfoPtr->MCastIp.Addr[0] == 0 ||\r
-        MtftpInfoPtr->SPort == 0 ||\r
-        MtftpInfoPtr->CPort == 0 ||\r
-        MtftpInfoPtr->ListenTimeout == 0 ||\r
-        MtftpInfoPtr->TransmitTimeout == 0\r
-        ) {\r
-      StatCode = EFI_INVALID_PARAMETER;\r
-      break;\r
-    }\r
-    //\r
-    // try MTFTP - if fails, drop into TFTP read\r
-    //\r
-    if ((StatCode = MtftpDownload (\r
-                      Private,\r
-                      &BufferSizeLocal,\r
-                      BufferPtrLocal,\r
-                      ServerIpPtr,\r
-                      FilenamePtr,\r
-                      MtftpInfoPtr,\r
-                      DontUseBuffer\r
-                      )) == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {\r
-      if (BufferSizePtr /* %% !DontUseBuffer */ ) {\r
-        *BufferSizePtr = BufferSizeLocal;\r
-      }\r
-\r
-      break;\r
-    }\r
-    //\r
-    // go back to unicast\r
-    //\r
-    if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {\r
-      break;\r
-    }\r
-\r
-  /* fall thru */\r
-  case EFI_PXE_BASE_CODE_TFTP_READ_FILE:\r
-    if (FilenamePtr == NULL) {\r
-      StatCode = EFI_INVALID_PARAMETER;\r
-      break;\r
-    }\r
-\r
-    StatCode = TftpDownload (\r
-                Private,\r
-                &BufferSizeLocal,\r
-                BufferPtrLocal,\r
-                ServerIpPtr,\r
-                FilenamePtr,\r
-                PacketSizePtr,\r
-                TftpRequestPort,\r
-                TFTP_RRQ,\r
-                DontUseBuffer\r
-                );\r
-\r
-    if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {\r
-      if (BufferSizePtr /* !DontUseBuffer */ ) {\r
-        *BufferSizePtr = BufferSizeLocal;\r
-      }\r
-    }\r
-\r
-    break;\r
-\r
-  case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:\r
-    if (FilenamePtr == NULL || DontUseBuffer) {\r
-      //\r
-      // not a valid option\r
-      //\r
-      StatCode = EFI_INVALID_PARAMETER;\r
-      break;\r
-    }\r
-\r
-    StatCode = TftpUpload (\r
-                Private,\r
-                BufferSizePtr,\r
-                BufferPtr,\r
-                ServerIpPtr,\r
-                FilenamePtr,\r
-                PacketSizePtr,\r
-                Overwrite\r
-                );\r
-\r
-    if (StatCode != EFI_SUCCESS) {\r
-      DEBUG (\r
-        (EFI_D_WARN,\r
-        "\nPxeBcMtftp()  Exit #6  %xh (%r)",\r
-        StatCode,\r
-        StatCode)\r
-        );\r
-    }\r
-\r
-    return StatCode;\r
-\r
-  case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:\r
-    if (FilenamePtr == NULL || DontUseBuffer) {\r
-      //\r
-      // not a valid option\r
-      //\r
-      StatCode = EFI_INVALID_PARAMETER;\r
-      break;\r
-    }\r
-\r
-    StatCode = TftpDownload (\r
-                Private,\r
-                BufferSizePtr,\r
-                BufferPtr,\r
-                ServerIpPtr,\r
-                FilenamePtr,\r
-                PacketSizePtr,\r
-                TftpRequestPort,\r
-                TFTP_DIR,\r
-                DontUseBuffer\r
-                );\r
-\r
-    if (StatCode != EFI_SUCCESS) {\r
-      DEBUG (\r
-        (EFI_D_WARN,\r
-        "\nPxeBcMtftp()  Exit #7  %xh (%r)",\r
-        StatCode,\r
-        StatCode)\r
-        );\r
-    }\r
-\r
-    return StatCode;\r
-\r
-  case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:\r
-    if (DontUseBuffer) {\r
-      StatCode = EFI_INVALID_PARAMETER;\r
-      break;\r
-    }\r
-\r
-    if (MtftpInfoPtr == NULL || !MtftpInfoPtr->SPort) {\r
-      DEBUG (\r
-        (EFI_D_WARN,\r
-        "\nPxeBcMtftp()  Exit #9  %xh (%r)",\r
-        EFI_INVALID_PARAMETER,\r
-        EFI_INVALID_PARAMETER)\r
-        );\r
-\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    StatCode = TftpDownload (\r
-                Private,\r
-                BufferSizePtr,\r
-                BufferPtr,\r
-                ServerIpPtr,\r
-                (UINT8 *) "/",\r
-                PacketSizePtr,\r
-                MtftpInfoPtr->SPort,\r
-                TFTP_DIR,\r
-                DontUseBuffer\r
-                );\r
-\r
-    break;\r
-\r
-  default:\r
-    StatCode = EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DontUseBuffer) {\r
-    FreePool (BufferPtrLocal);\r
-  }\r
-\r
-  if (StatCode != EFI_SUCCESS) {\r
-    DEBUG (\r
-      (EFI_D_WARN,\r
-      "\nPxeBcMtftp()  Exit #8  %xh (%r)",\r
-      StatCode,\r
-      StatCode)\r
-      );\r
-  }\r
-\r
-  gBS->Stall (10000);\r
-\r
-  return StatCode;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-EFI_STATUS\r
-EFIAPI\r
-BcMtftp (\r
-  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,\r
-  IN EFI_PXE_BASE_CODE_TFTP_OPCODE    Operation,\r
-  IN OUT VOID                         *BufferPtr,\r
-  IN BOOLEAN                          Overwrite,\r
-  IN OUT UINT64                       *BufferSizePtr,\r
-  IN UINTN                            *BlockSizePtr OPTIONAL,\r
-  IN EFI_IP_ADDRESS                   * ServerIpPtr,\r
-  IN UINT8                            *FilenamePtr,\r
-  IN EFI_PXE_BASE_CODE_MTFTP_INFO     * MtftpInfoPtr OPTIONAL,\r
-  IN BOOLEAN                          DontUseBuffer\r
-  )\r
-/*++\r
-Routine description:\r
-  MTFTP API entry point.\r
-\r
-Parameters:\r
-  This :=\r
-  Operation :=\r
-  BufferPtr :=\r
-  Overwrite :=\r
-  BufferSizePtr :=\r
-  BlockSizePtr :=\r
-  ServerIpPtr :=\r
-  FilenamePtr :=\r
-  MtftpInfoPtr :=\r
-  DontUseBuffer :=\r
-\r
-Returns:\r
- *  EFI_INVALID_PARAMETER\r
- *  Status is also returned from PxeBcMtftp();\r
---*/\r
-{\r
-  EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
-  EFI_STATUS                  StatCode;\r
-  PXE_BASECODE_DEVICE         *Private;\r
-\r
-  //\r
-  // Lock the instance data and make sure started\r
-  //\r
-  StatCode = EFI_SUCCESS;\r
-\r
-  if (This == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
-  if (Private == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  EfiAcquireLock (&Private->Lock);\r
-\r
-  if (This->Mode == NULL || !This->Mode->Started) {\r
-    DEBUG ((EFI_D_ERROR, "BC was not started."));\r
-    EfiReleaseLock (&Private->Lock);\r
-    return EFI_NOT_STARTED;\r
-  }\r
-  //\r
-  // Issue BC command\r
-  //\r
-  Filter.Filters  = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
-  Filter.IpCnt    = 0;\r
-  Filter.reserved = 0;\r
-\r
-  DEBUG ((EFI_D_WARN, "\nBcMtftp()  Op=%d  Buf=%Xh", Operation, BufferPtr));\r
-\r
-  StatCode = PxeBcMtftp (\r
-              Private,\r
-              Operation,\r
-              BufferSizePtr,\r
-              BufferPtr,\r
-              ServerIpPtr,\r
-              FilenamePtr,\r
-              BlockSizePtr,\r
-              MtftpInfoPtr,\r
-              Overwrite,\r
-              DontUseBuffer\r
-              );\r
-\r
-  //\r
-  // restore to unicast\r
-  //\r
-  IpFilter (Private, &Filter);\r
-\r
-  //\r
-  // Unlock the instance data\r
-  //\r
-  EfiReleaseLock (&Private->Lock);\r
-  return StatCode;\r
-}\r
-\r
-/* eof - PxeBcMtftp.c */\r