1 /** @file 2 Definitions for the TFTP server. 3 4 Copyright (c) 2011, 2012, Intel Corporation 5 All rights reserved. This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #ifndef _TFTP_SERVER_H_ 16 #define _TFTP_SERVER_H_ 17 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <Uefi.h> 23 24 #include <Guid/EventGroup.h> 25 26 #include <Library/BaseMemoryLib.h> 27 #include <Library/DebugLib.h> 28 #include <Library/MemoryAllocationLib.h> 29 #include <Library/PcdLib.h> 30 #include <Library/TimerLib.h> 31 #include <Library/UefiApplicationEntryPoint.h> 32 #include <Library/UefiBootServicesTableLib.h> 33 #include <Library/UefiLib.h> 34 #include <Protocol/BlockIo.h> 35 36 #include <netinet/in.h> 37 #include <netinet6/in6.h> 38 39 #include <sys/EfiSysCall.h> 40 #include <sys/poll.h> 41 #include <sys/socket.h> 42 #include <sys/stat.h> 43 44 //------------------------------------------------------------------------------ 45 // Macros 46 //------------------------------------------------------------------------------ 47 48 #if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */ 49 #define DBG_ENTER() DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry 50 #define DBG_EXIT() DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit 51 #define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value 52 #define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value 53 #define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value 54 #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 55 #else // _MSC_VER 56 #define DBG_ENTER() 57 #define DBG_EXIT() 58 #define DBG_EXIT_DEC(Status) 59 #define DBG_EXIT_HEX(Status) 60 #define DBG_EXIT_STATUS(Status) 61 #define DBG_EXIT_TF(Status) 62 #endif // _MSC_VER 63 64 #define DIM(x) ( sizeof ( x ) / sizeof ( x[0] )) ///< Compute the number of entries in an array 65 66 //------------------------------------------------------------------------------ 67 // Constants 68 //------------------------------------------------------------------------------ 69 70 #define ACK_SHIFT 4 ///< Number of samples in ACK average 71 72 #define DEBUG_WINDOW 0x00000001 ///< Display the window messages 73 #define DEBUG_TX_PACKET 0x00000002 ///< Display the transmit packet messages 74 #define DEBUG_FILE_BUFFER 0x00000004 ///< Display the file buffer messages 75 #define DEBUG_SERVER_TIMER 0x00000008 ///< Display the socket poll messages 76 #define DEBUG_TFTP_REQUEST 0x00000010 ///< Display the TFTP request messages 77 #define DEBUG_PORT_WORK 0x00000020 ///< Display the port work messages 78 #define DEBUG_SOCKET_POLL 0x00000040 ///< Display the socket poll messages 79 #define DEBUG_TFTP_PORT 0x00000080 ///< Display the TFTP port messages 80 #define DEBUG_TX 0x00000100 ///< Display transmit messages 81 #define DEBUG_RX 0x00000200 ///< Display receive messages 82 #define DEBUG_TFTP_ACK 0x00000400 ///< Display the TFTP ACK messages 83 #define DEBUG_ENTER_EXIT 0x00000800 ///< Display entry and exit messages 84 85 #define MAX_PACKETS 8 ///< Maximum number of packets in the window 86 87 #define TFTP_PORT_POLL_DELAY ( 2 * 1000 ) ///< Delay in milliseconds for attempts to open the TFTP port 88 #define CLIENT_POLL_DELAY 50 ///< Delay in milliseconds between client polls 89 90 #define TPL_TFTP_SERVER TPL_CALLBACK ///< TPL for routine synchronization 91 92 /** 93 Verify new TPL value 94 95 This macro which is enabled when debug is enabled verifies that 96 the new TPL value is >= the current TPL value. 97 **/ 98 #ifdef VERIFY_TPL 99 #undef VERIFY_TPL 100 #endif // VERIFY_TPL 101 102 #if !defined(MDEPKG_NDEBUG) 103 104 #define VERIFY_TPL(tpl) \ 105 { \ 106 EFI_TPL PreviousTpl; \ 107 \ 108 PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \ 109 gBS->RestoreTPL ( PreviousTpl ); \ 110 if ( PreviousTpl > tpl ) { \ 111 DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl )); \ 112 ASSERT ( PreviousTpl <= tpl ); \ 113 } \ 114 } 115 116 #else // MDEPKG_NDEBUG 117 118 #define VERIFY_TPL(tpl) 119 120 #endif // MDEPKG_NDEBUG 121 122 #define TFTP_SERVER_SIGNATURE SIGNATURE_32('T','F','T','P') ///< TSDT_TFTP_SERVER memory signature 123 124 // 125 // See: http://www.rfc-editor.org/rfc/pdfrfc/rfc1350.txt.pdf 126 // 127 // TFTP Operations 128 // 129 130 #define TFTP_OP_READ_REQUEST 1 ///< Read request, zero terminated file name, zero terminated mode 131 #define TFTP_OP_WRITE_REQUEST 2 ///< Write request, zero terminated file name, zero terminated mode 132 #define TFTP_OP_DATA 3 ///< Data block, end-of-file indicated by short block 133 #define TFTP_OP_ACK 4 ///< ACK block number 134 #define TFTP_OP_ERROR 5 ///< Error number and explaination 135 #define TFTP_OP_OACK 6 ///< ACK the options 136 137 #define TFTP_MAX_BLOCK_SIZE 4096 ///< Maximum block size 138 139 #define TFTP_ERROR_SEE_MSG 0 ///< See the error message 140 #define TFTP_ERROR_NOT_FOUND 1 ///< File not found 141 #define TFTP_ERROR_ACCESS_VIOLATION 2 ///< Access violation 142 #define TFTP_ERROR_DISK_FULL 3 ///< Disk full 143 #define TFTP_ERROR_ILLEGAL_OP 4 ///< Illegal operation 144 #define TFTP_ERROR_UNKNOWN_XFER_ID 5 ///< Unknown transfer ID 145 #define TFTP_ERROR_FILE_EXISTS 6 ///< File already exists 146 #define TFTP_ERROR_NO_SUCH_USER 7 ///< No such user 147 148 //------------------------------------------------------------------------------ 149 // Data Types 150 //------------------------------------------------------------------------------ 151 152 /** 153 Packet structure 154 **/ 155 typedef struct _TFTP_PACKET TFTP_PACKET; 156 typedef struct _TFTP_PACKET { 157 TFTP_PACKET * pNext; ///< Next packet in list 158 UINT64 TxTime; ///< Time the transmit was performed 159 ssize_t TxBytes; ///< Bytes in the TX buffer 160 UINT32 RetryCount; ///< Number of transmissions 161 UINT16 BlockNumber; ///< Block number of this packet 162 UINT8 TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Transmit buffer 163 } GCC_TFTP_PACKET; 164 165 /** 166 Port control structure 167 **/ 168 typedef struct _TSDT_CONNECTION_CONTEXT TSDT_CONNECTION_CONTEXT; 169 typedef struct _TSDT_CONNECTION_CONTEXT { 170 // 171 // Remote connection management 172 // 173 TSDT_CONNECTION_CONTEXT * pNext; ///< Next context in the connection list 174 struct sockaddr_in6 RemoteAddress; ///< Remote address 175 int SocketFd; ///< Socket file descriptor 176 177 // 178 // File management parameters 179 // 180 FILE * File; ///< NULL while file is closed 181 UINT64 LengthInBytes; ///< Size of the file 182 UINT64 BytesRemaining; ///< Number of bytes remaining to be sent 183 UINT64 BytesToSend; ///< Number of bytes to send 184 UINT64 ValidBytes; ///< Number of valid bytes in the buffer 185 BOOLEAN bEofSent; ///< End of file sent 186 UINT8 * pFill; ///< Next portion of the buffer to fill 187 UINT8 * pBuffer; ///< Pointer into the file data 188 UINT8 * pEnd; ///< End of the file data 189 UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ]; ///< File data to send 190 UINT64 TimeStart; ///< Start of file transfer 191 192 // 193 // TFTP management parameters 194 // 195 UINT16 BlockNumber; ///< Next block to be transmitted 196 UINT32 BlockSize; ///< Negotiated block size 197 198 // 199 // Window management 200 // 201 UINT32 AckCount; ///< Number of ACKs to receive before increasing the window 202 UINT32 PacketsInWindow; ///< Number of packets in the window 203 UINT32 Threshold; ///< Size of window when ACK count becomes logrithmic 204 UINT32 WindowSize; ///< Size of the transmit window 205 UINT64 MaxTimeout; ///< Maximum number of seconds to wait before retransmission 206 UINT64 Rtt2x; ///< Twice the average round trip time in nanoseconds 207 208 // 209 // Buffer management 210 // 211 TFTP_PACKET * pFreeList; ///< List of free packets 212 TFTP_PACKET * pTxHead; ///< First packet in the list of packets for transmission 213 TFTP_PACKET * pTxTail; ///< Last packet in the list of packets for transmission 214 TFTP_PACKET ErrorPacket; ///< Error packet 215 TFTP_PACKET Tx[ MAX_PACKETS ];///< Transmit packets 216 }GCC_TSDT_CONNECTION_CONTEXT; 217 218 /** 219 TFTP server control structure 220 **/ 221 typedef struct { 222 UINTN Signature; ///< Structure identification 223 224 // 225 // Image attributes 226 // 227 EFI_HANDLE ImageHandle; ///< Image handle 228 229 // 230 // Performance management 231 // 232 UINT64 ClockFrequency; ///< Frequency of the clock 233 UINT64 Time1; ///< Clock value after rollover 234 UINT64 Time2; ///< Clock value before rollover 235 UINT64 RxTime; ///< Time when the packet was recevied 236 237 // 238 // TFTP port management 239 // 240 EFI_EVENT TimerEvent; ///< Timer to open TFTP port 241 int Udpv4Index; ///< Entry for UDPv4 242 int Udpv6Index; ///< Entry for UDPv6 243 int Entries; ///< Number of TFTP ports 244 struct pollfd TftpPort [ 2 ]; ///< Poll descriptor for the TFTP ports (UDP4, UDP6) 245 246 // 247 // Request management 248 // 249 union { 250 struct sockaddr_in v4; ///< UDP4 address 251 struct sockaddr_in6 v6; ///< UDP6 address 252 } RemoteAddress; ///< Remote address 253 ssize_t RxBytes; ///< Receive data length in bytes 254 UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Receive buffer 255 256 // 257 // Client port management 258 // 259 TSDT_CONNECTION_CONTEXT * pContextList; ///< List of connection context structures 260 } TSDT_TFTP_SERVER; 261 262 //#define SERVER_FROM_SERVICE(a) CR(a, TSDT_TFTP_SERVER, ServiceBinding, TFTP_SERVER_SIGNATURE) ///< Locate DT_LAYER from service binding 263 264 extern TSDT_TFTP_SERVER mTftpServer; 265 266 //------------------------------------------------------------------------------ 267 // Support routines 268 //------------------------------------------------------------------------------ 269 270 /** 271 Queue data packets for transmission 272 273 @param [in] pContext Connection context structure address 274 275 @retval TRUE if a read error occurred 276 277 **/ 278 BOOLEAN 279 PacketFill ( 280 IN TSDT_CONNECTION_CONTEXT * pContext 281 ); 282 283 /** 284 Free the packet 285 286 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 287 @param [in] pPacket Address of a ::TFTP_PACKET structure 288 289 **/ 290 VOID 291 PacketFree( 292 IN TSDT_CONNECTION_CONTEXT * pContext, 293 IN TFTP_PACKET * pPacket 294 ); 295 296 /** 297 Get a packet for transmission 298 299 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 300 301 @retval Address of a ::TFTP_PACKET structure 302 303 **/ 304 TFTP_PACKET * 305 PacketGet ( 306 IN TSDT_CONNECTION_CONTEXT * pContext 307 ); 308 309 /** 310 Queue the packet for transmission 311 312 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 313 @param [in] pPacket Address of a ::TFTP_PACKET structure 314 315 @retval TRUE if a transmission error has occurred 316 317 **/ 318 BOOLEAN 319 PacketQueue ( 320 IN TSDT_CONNECTION_CONTEXT * pContext, 321 IN TFTP_PACKET * pPacket 322 ); 323 324 /** 325 Transmit the packet 326 327 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 328 @param [in] pPacket Address of a ::TFTP_PACKET structure 329 330 @retval EFI_SUCCESS Message processed successfully 331 332 **/ 333 EFI_STATUS 334 PacketTx ( 335 IN TSDT_CONNECTION_CONTEXT * pContext, 336 IN TFTP_PACKET * pPacket 337 ); 338 339 /** 340 Build and send an error packet 341 342 @param [in] pContext The context structure address. 343 @param [in] Error Error number for the packet 344 @param [in] pError Zero terminated error string address 345 346 @retval EFI_SUCCESS Message processed successfully 347 348 **/ 349 EFI_STATUS 350 SendError ( 351 IN TSDT_CONNECTION_CONTEXT * pContext, 352 IN UINT16 Error, 353 IN UINT8 * pError 354 ); 355 356 /** 357 Process the TFTP request 358 359 @param [in] pOption Address of the first zero terminated option string 360 @param [in] pValue Address to receive the value 361 362 @retval EFI_SUCCESS Option translated into a value 363 364 **/ 365 EFI_STATUS 366 TftpOptionValue ( 367 IN UINT8 * pOption, 368 IN INT32 * pValue 369 ); 370 371 /** 372 Process the TFTP request 373 374 @param [in] pTftpServer The TFTP server control structure address. 375 @param [in] pContext Connection context structure address 376 @param [in] SocketFd Socket file descriptor 377 378 **/ 379 VOID 380 TftpProcessRequest ( 381 IN TSDT_TFTP_SERVER * pTftpServer, 382 IN TSDT_CONNECTION_CONTEXT * pContext, 383 IN int SocketFd 384 ); 385 386 /** 387 Process the read request 388 389 @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure 390 @param [in] pContext Connection context structure address 391 @param [in] SocketFd Socket file descriptor 392 393 @retval TRUE if the context should be closed 394 395 **/ 396 BOOLEAN 397 TftpRead ( 398 IN TSDT_TFTP_SERVER * pTftpServer, 399 IN TSDT_CONNECTION_CONTEXT * pContext, 400 IN int SocketFd 401 ); 402 403 /** 404 Update the window due to the ACK 405 406 @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure 407 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 408 @param [in] pPacket Address of a ::TFTP_PACKET structure 409 410 **/ 411 VOID 412 WindowAck ( 413 IN TSDT_TFTP_SERVER * pTftpServer, 414 IN TSDT_CONNECTION_CONTEXT * pContext, 415 IN TFTP_PACKET * pPacket 416 ); 417 418 /** 419 A timeout has occurred, close the window 420 421 @param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure 422 423 **/ 424 VOID 425 WindowTimeout ( 426 IN TSDT_CONNECTION_CONTEXT * pContext 427 ); 428 429 //------------------------------------------------------------------------------ 430 431 #endif // _TFTP_SERVER_H_ 432