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