Change “#include <sys/Stat.h>” to “#include <sys/stat.h>”. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Daryl McDaniel <daryl.mcdaniel@intel.com> Reviewed-by: Leahy, Leroy P <leroy.p.leahy@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15891 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			432 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			432 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Definitions for the TFTP server.
 | |
| 
 | |
|   Copyright (c) 2011, 2012, Intel Corporation
 | |
|   All rights reserved. This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #ifndef _TFTP_SERVER_H_
 | |
| #define _TFTP_SERVER_H_
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <Uefi.h>
 | |
| 
 | |
| #include <Guid/EventGroup.h>
 | |
| 
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/TimerLib.h>
 | |
| #include <Library/UefiApplicationEntryPoint.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include <Protocol/BlockIo.h>
 | |
| 
 | |
| #include <netinet/in.h>
 | |
| #include <netinet6/in6.h>
 | |
| 
 | |
| #include <sys/EfiSysCall.h>
 | |
| #include <sys/poll.h>
 | |
| #include <sys/socket.h>
 | |
| #include <sys/stat.h>
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| //  Macros
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| #if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */
 | |
| #define DBG_ENTER()             DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry
 | |
| #define DBG_EXIT()              DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit
 | |
| #define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value
 | |
| #define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value
 | |
| #define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value
 | |
| #define DBG_EXIT_TF(Status)     DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" ))  ///<  Display routine with TRUE/FALSE value
 | |
| #else   //  _MSC_VER
 | |
| #define DBG_ENTER()
 | |
| #define DBG_EXIT()
 | |
| #define DBG_EXIT_DEC(Status)
 | |
| #define DBG_EXIT_HEX(Status)
 | |
| #define DBG_EXIT_STATUS(Status)
 | |
| #define DBG_EXIT_TF(Status)
 | |
| #endif  //  _MSC_VER
 | |
| 
 | |
| #define DIM(x)    ( sizeof ( x ) / sizeof ( x[0] ))   ///<  Compute the number of entries in an array
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| //  Constants
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| #define ACK_SHIFT               4           ///<  Number of samples in ACK average
 | |
| 
 | |
| #define DEBUG_WINDOW            0x00000001  ///<  Display the window messages
 | |
| #define DEBUG_TX_PACKET         0x00000002  ///<  Display the transmit packet messages
 | |
| #define DEBUG_FILE_BUFFER       0x00000004  ///<  Display the file buffer messages
 | |
| #define DEBUG_SERVER_TIMER      0x00000008  ///<  Display the socket poll messages
 | |
| #define DEBUG_TFTP_REQUEST      0x00000010  ///<  Display the TFTP request messages
 | |
| #define DEBUG_PORT_WORK         0x00000020  ///<  Display the port work messages
 | |
| #define DEBUG_SOCKET_POLL       0x00000040  ///<  Display the socket poll messages
 | |
| #define DEBUG_TFTP_PORT         0x00000080  ///<  Display the TFTP port messages
 | |
| #define DEBUG_TX                0x00000100  ///<  Display transmit messages
 | |
| #define DEBUG_RX                0x00000200  ///<  Display receive messages
 | |
| #define DEBUG_TFTP_ACK          0x00000400  ///<  Display the TFTP ACK messages
 | |
| #define DEBUG_ENTER_EXIT        0x00000800  ///<  Display entry and exit messages
 | |
| 
 | |
| #define MAX_PACKETS             8           ///<  Maximum number of packets in the window
 | |
| 
 | |
| #define TFTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the TFTP port
 | |
| #define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls
 | |
| 
 | |
| #define TPL_TFTP_SERVER        TPL_CALLBACK ///<  TPL for routine synchronization
 | |
| 
 | |
| /**
 | |
|   Verify new TPL value
 | |
| 
 | |
|   This macro which is enabled when debug is enabled verifies that
 | |
|   the new TPL value is >= the current TPL value.
 | |
| **/
 | |
| #ifdef VERIFY_TPL
 | |
| #undef VERIFY_TPL
 | |
| #endif  //  VERIFY_TPL
 | |
| 
 | |
| #if !defined(MDEPKG_NDEBUG)
 | |
| 
 | |
| #define VERIFY_TPL(tpl)                           \
 | |
| {                                                 \
 | |
|   EFI_TPL PreviousTpl;                            \
 | |
|                                                   \
 | |
|   PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \
 | |
|   gBS->RestoreTPL ( PreviousTpl );                \
 | |
|   if ( PreviousTpl > tpl ) {                      \
 | |
|     DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl ));  \
 | |
|     ASSERT ( PreviousTpl <= tpl );                \
 | |
|   }                                               \
 | |
| }
 | |
| 
 | |
| #else   //  MDEPKG_NDEBUG
 | |
| 
 | |
| #define VERIFY_TPL(tpl)
 | |
| 
 | |
| #endif  //  MDEPKG_NDEBUG
 | |
| 
 | |
| #define TFTP_SERVER_SIGNATURE       SIGNATURE_32('T','F','T','P') ///<  TSDT_TFTP_SERVER memory signature
 | |
| 
 | |
| //
 | |
| //  See: http://www.rfc-editor.org/rfc/pdfrfc/rfc1350.txt.pdf
 | |
| //
 | |
| //  TFTP Operations
 | |
| //
 | |
| 
 | |
| #define TFTP_OP_READ_REQUEST      1     ///<  Read request, zero terminated file name, zero terminated mode
 | |
| #define TFTP_OP_WRITE_REQUEST     2     ///<  Write request, zero terminated file name, zero terminated mode
 | |
| #define TFTP_OP_DATA              3     ///<  Data block, end-of-file indicated by short block
 | |
| #define TFTP_OP_ACK               4     ///<  ACK block number
 | |
| #define TFTP_OP_ERROR             5     ///<  Error number and explaination
 | |
| #define TFTP_OP_OACK              6     ///<  ACK the options
 | |
| 
 | |
| #define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size
 | |
| 
 | |
| #define TFTP_ERROR_SEE_MSG          0   ///<  See the error message
 | |
| #define TFTP_ERROR_NOT_FOUND        1   ///<  File not found
 | |
| #define TFTP_ERROR_ACCESS_VIOLATION 2   ///<  Access violation
 | |
| #define TFTP_ERROR_DISK_FULL        3   ///<  Disk full
 | |
| #define TFTP_ERROR_ILLEGAL_OP       4   ///<  Illegal operation
 | |
| #define TFTP_ERROR_UNKNOWN_XFER_ID  5   ///<  Unknown transfer ID
 | |
| #define TFTP_ERROR_FILE_EXISTS      6   ///<  File already exists
 | |
| #define TFTP_ERROR_NO_SUCH_USER     7   ///<  No such user
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| //  Data Types
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| /**
 | |
|   Packet structure
 | |
| **/
 | |
| typedef struct _TFTP_PACKET TFTP_PACKET;
 | |
| typedef struct _TFTP_PACKET {
 | |
|   TFTP_PACKET * pNext;          ///<  Next packet in list
 | |
|   UINT64    TxTime;             ///<  Time the transmit was performed
 | |
|   ssize_t   TxBytes;            ///<  Bytes in the TX buffer
 | |
|   UINT32    RetryCount;         ///<  Number of transmissions
 | |
|   UINT16    BlockNumber;        ///<  Block number of this packet
 | |
|   UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer
 | |
| } GCC_TFTP_PACKET;
 | |
| 
 | |
| /**
 | |
|   Port control structure
 | |
| **/
 | |
| typedef struct _TSDT_CONNECTION_CONTEXT TSDT_CONNECTION_CONTEXT;
 | |
| typedef struct _TSDT_CONNECTION_CONTEXT {
 | |
|   //
 | |
|   //  Remote connection management
 | |
|   //
 | |
|   TSDT_CONNECTION_CONTEXT * pNext;    ///<  Next context in the connection list
 | |
|   struct sockaddr_in6 RemoteAddress;  ///<  Remote address
 | |
|   int SocketFd;                       ///<  Socket file descriptor
 | |
| 
 | |
|   //
 | |
|   //  File management parameters
 | |
|   //
 | |
|   FILE * File;                  ///<  NULL while file is closed
 | |
|   UINT64 LengthInBytes;         ///<  Size of the file
 | |
|   UINT64 BytesRemaining;        ///<  Number of bytes remaining to be sent
 | |
|   UINT64 BytesToSend;           ///<  Number of bytes to send
 | |
|   UINT64 ValidBytes;            ///<  Number of valid bytes in the buffer
 | |
|   BOOLEAN bEofSent;             ///<  End of file sent
 | |
|   UINT8 * pFill;                ///<  Next portion of the buffer to fill
 | |
|   UINT8 * pBuffer;              ///<  Pointer into the file data
 | |
|   UINT8 * pEnd;                 ///<  End of the file data
 | |
|   UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ];  ///<  File data to send
 | |
|   UINT64 TimeStart;             ///<  Start of file transfer
 | |
| 
 | |
|   //
 | |
|   //  TFTP management parameters
 | |
|   //
 | |
|   UINT16 BlockNumber;           ///<  Next block to be transmitted
 | |
|   UINT32 BlockSize;             ///<  Negotiated block size
 | |
| 
 | |
|   //
 | |
|   //  Window management
 | |
|   //
 | |
|   UINT32 AckCount;              ///<  Number of ACKs to receive before increasing the window
 | |
|   UINT32 PacketsInWindow;       ///<  Number of packets in the window
 | |
|   UINT32 Threshold;             ///<  Size of window when ACK count becomes logrithmic
 | |
|   UINT32 WindowSize;            ///<  Size of the transmit window
 | |
|   UINT64 MaxTimeout;            ///<  Maximum number of seconds to wait before retransmission
 | |
|   UINT64 Rtt2x;                 ///<  Twice the average round trip time in nanoseconds
 | |
| 
 | |
|   //
 | |
|   //  Buffer management
 | |
|   //
 | |
|   TFTP_PACKET * pFreeList;      ///<  List of free packets
 | |
|   TFTP_PACKET * pTxHead;        ///<  First packet in the list of packets for transmission
 | |
|   TFTP_PACKET * pTxTail;        ///<  Last packet in the list of packets for transmission
 | |
|   TFTP_PACKET ErrorPacket;      ///<  Error packet
 | |
|   TFTP_PACKET Tx[ MAX_PACKETS ];///<  Transmit packets
 | |
| }GCC_TSDT_CONNECTION_CONTEXT;
 | |
| 
 | |
| /**
 | |
|   TFTP server control structure
 | |
| **/
 | |
| typedef struct {
 | |
|   UINTN Signature;              ///<  Structure identification
 | |
| 
 | |
|   //
 | |
|   //  Image attributes
 | |
|   //
 | |
|   EFI_HANDLE ImageHandle;       ///<  Image handle
 | |
| 
 | |
|   //
 | |
|   //  Performance management
 | |
|   //
 | |
|   UINT64 ClockFrequency;        ///<  Frequency of the clock
 | |
|   UINT64 Time1;                 ///<  Clock value after rollover
 | |
|   UINT64 Time2;                 ///<  Clock value before rollover
 | |
|   UINT64 RxTime;                ///<  Time when the packet was recevied
 | |
| 
 | |
|   //
 | |
|   //  TFTP port management
 | |
|   //
 | |
|   EFI_EVENT TimerEvent;         ///<  Timer to open TFTP port
 | |
|   int Udpv4Index;               ///<  Entry for UDPv4
 | |
|   int Udpv6Index;               ///<  Entry for UDPv6
 | |
|   int Entries;                  ///<  Number of TFTP ports
 | |
|   struct pollfd TftpPort [ 2 ]; ///<  Poll descriptor for the TFTP ports (UDP4, UDP6)
 | |
| 
 | |
|   //
 | |
|   //  Request management
 | |
|   //
 | |
|   union {
 | |
|     struct sockaddr_in v4;      ///<  UDP4 address
 | |
|     struct sockaddr_in6 v6;     ///<  UDP6 address
 | |
|   } RemoteAddress;              ///<  Remote address
 | |
|   ssize_t RxBytes;              ///<  Receive data length in bytes
 | |
|   UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer
 | |
| 
 | |
|   //
 | |
|   //  Client port management
 | |
|   //
 | |
|   TSDT_CONNECTION_CONTEXT * pContextList; ///<  List of connection context structures
 | |
| } TSDT_TFTP_SERVER;
 | |
| 
 | |
| //#define SERVER_FROM_SERVICE(a) CR(a, TSDT_TFTP_SERVER, ServiceBinding, TFTP_SERVER_SIGNATURE) ///< Locate DT_LAYER from service binding
 | |
| 
 | |
| extern TSDT_TFTP_SERVER mTftpServer;
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Support routines
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| /**
 | |
|   Queue data packets for transmission
 | |
| 
 | |
|   @param [in] pContext    Connection context structure address
 | |
| 
 | |
|   @retval TRUE if a read error occurred
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| PacketFill (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Free the packet
 | |
| 
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
|   @param [in] pPacket     Address of a ::TFTP_PACKET structure
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PacketFree(
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN TFTP_PACKET * pPacket
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get a packet for transmission
 | |
| 
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
| 
 | |
|   @retval Address of a ::TFTP_PACKET structure
 | |
| 
 | |
| **/
 | |
| TFTP_PACKET *
 | |
| PacketGet (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Queue the packet for transmission
 | |
| 
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
|   @param [in] pPacket     Address of a ::TFTP_PACKET structure
 | |
| 
 | |
|   @retval TRUE if a transmission error has occurred
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| PacketQueue (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN TFTP_PACKET * pPacket
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Transmit the packet
 | |
| 
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
|   @param [in] pPacket     Address of a ::TFTP_PACKET structure
 | |
| 
 | |
|   @retval EFI_SUCCESS   Message processed successfully
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| PacketTx (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN TFTP_PACKET * pPacket
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Build and send an error packet
 | |
| 
 | |
|   @param [in] pContext    The context structure address.
 | |
|   @param [in] Error       Error number for the packet
 | |
|   @param [in] pError      Zero terminated error string address
 | |
| 
 | |
|   @retval EFI_SUCCESS     Message processed successfully
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SendError (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN UINT16 Error,
 | |
|   IN UINT8 * pError
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Process the TFTP request
 | |
| 
 | |
|   @param [in] pOption   Address of the first zero terminated option string
 | |
|   @param [in] pValue    Address to receive the value
 | |
| 
 | |
|   @retval EFI_SUCCESS   Option translated into a value
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| TftpOptionValue (
 | |
|   IN UINT8 * pOption,
 | |
|   IN INT32 * pValue
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Process the TFTP request
 | |
| 
 | |
|   @param [in] pTftpServer The TFTP server control structure address.
 | |
|   @param [in] pContext    Connection context structure address
 | |
|   @param [in] SocketFd    Socket file descriptor
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| TftpProcessRequest (
 | |
|   IN TSDT_TFTP_SERVER * pTftpServer,
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN int SocketFd
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Process the read request
 | |
| 
 | |
|   @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
 | |
|   @param [in] pContext    Connection context structure address
 | |
|   @param [in] SocketFd    Socket file descriptor
 | |
| 
 | |
|   @retval TRUE if the context should be closed
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| TftpRead (
 | |
|   IN TSDT_TFTP_SERVER * pTftpServer,
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN int SocketFd
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Update the window due to the ACK
 | |
| 
 | |
|   @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
|   @param [in] pPacket     Address of a ::TFTP_PACKET structure
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| WindowAck (
 | |
|   IN TSDT_TFTP_SERVER * pTftpServer,
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext,
 | |
|   IN TFTP_PACKET * pPacket
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   A timeout has occurred, close the window
 | |
| 
 | |
|   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| WindowTimeout (
 | |
|   IN TSDT_CONNECTION_CONTEXT * pContext
 | |
|   );
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| #endif  //  _TFTP_SERVER_H_
 |