• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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