1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
/** @file
Definitions for the TFTP server.
Copyright (c) 2011, 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 <stdlib.h>
#include <string.h>
#include <Uefi.h>
#include <Guid/EventGroup.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/BlockIo.h>
#include <netinet/in.h>
#include <sys/EfiSysCall.h>
#include <sys/poll.h>
#include <sys/socket.h>
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */
#define DBG_ENTER() DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry
#define DBG_EXIT() DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit
#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value
#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value
#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value
#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_INFO, "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 DEBUG_SOCKET_POLL 0x40000000 ///< Display the socket poll messages
#define DEBUG_PORT_WORK 0x20000000 ///< Display the port work messages
#define DEBUG_SERVER_TIMER 0x10000000 ///< Display the socket poll messages
#define DEBUG_TFTP_PORT 0x08000000 ///< Display the TFTP port messages
#define DEBUG_TFTP_REQUEST 0x04000000 ///< Display the TFTP request messages
#define DEBUG_TX 0x02000000 ///< Display transmit messages
#define DEBUG_RX 0x01000000 ///< Display receive messages
#define DEBUG_TFTP_ACK 0x00800000 ///< Display the TFTP ACK messages
#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
//------------------------------------------------------------------------------
// Data Types
//------------------------------------------------------------------------------
/**
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_in RemoteAddress; ///< Remote address
//
// TFTP management parameters
//
UINT16 AckNext; ///< Next block to be received
BOOLEAN bExpectAck; ///< TRUE for read, FALSE for write
UINT32 BlockSize; ///< Negotiated block size
UINT32 Timeout; ///< Number of seconds to wait before retransmission
//
// File management parameters
//
EFI_HANDLE File; ///< NULL while file is closed
UINT64 LengthInBytes; ///< Size of the file
UINT64 MaxTransferSize; ///< Maximum transfer size
BOOLEAN bEofSent; ///< End of file sent
UINT8 * pBuffer; ///< Pointer into the file data
UINT8 * pEnd; ///< End of the file data
UINT8 FileData [ 64 * TFTP_MAX_BLOCK_SIZE ]; ///< File data to send
//
// Buffer management
//
ssize_t TxBytes; ///< Bytes in the TX buffer
UINT8 TxBuffer [ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Transmit buffer
}GCC_TSDT_CONNECTION_CONTEXT;
/**
TFTP server control structure
**/
typedef struct {
UINTN Signature; ///< Structure identification
//
// Image attributes
//
EFI_HANDLE ImageHandle; ///< Image handle
//
// TFTP port management
//
BOOLEAN bTimerRunning; ///< Port creation timer status
EFI_EVENT TimerEvent; ///< Timer to open TFTP port
struct pollfd TftpPort; ///< Poll descriptor for the TFTP port
struct sockaddr_in TftpServerAddress; ///< Address of the local TFTP server
//
// Request management
//
struct sockaddr_in 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
//------------------------------------------------------------------------------
/**
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
**/
VOID
TftpProcessRequest (
IN TSDT_TFTP_SERVER * pTftpServer,
IN TSDT_CONNECTION_CONTEXT * pContext
);
/**
Build and send an error packet
@param [in] pTftpServer The TFTP server control structure address.
@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
TftpSendError (
IN TSDT_TFTP_SERVER * pTftpServer,
IN TSDT_CONNECTION_CONTEXT * pContext,
IN UINT16 Error,
IN UINT8 * pError
);
/**
Send the next block of file system data
@param [in] pTftpServer The TFTP server control structure address.
@param [in] pContext The context structure address.
@retval EFI_SUCCESS Message processed successfully
**/
EFI_STATUS
TftpSendNextBlock (
IN TSDT_TFTP_SERVER * pTftpServer,
IN TSDT_CONNECTION_CONTEXT * pContext
);
/**
TFTP port creation timer routine
This routine polls the socket layer waiting for the initial network connection
which will enable the creation of the TFTP port. The socket layer will manage
the coming and going of the network connections after that until the last network
connection is broken.
@param [in] pTftpServer The TFTP server control structure address.
**/
VOID
TftpServerTimer (
IN TSDT_TFTP_SERVER * pTftpServer
);
/**
Start the TFTP server port creation timer
@param [in] pTftpServer The TFTP server control structure address.
@retval EFI_SUCCESS The timer was successfully started.
@retval EFI_ALREADY_STARTED The timer is already running.
@retval Other The timer failed to start.
**/
EFI_STATUS
TftpServerTimerStart (
IN TSDT_TFTP_SERVER * pTftpServer
);
/**
Stop the TFTP server port creation timer
@param [in] pTftpServer The TFTP server control structure address.
@retval EFI_SUCCESS The TFTP port timer is stopped
@retval Other Failed to stop the TFTP port timer
**/
EFI_STATUS
TftpServerTimerStop (
IN TSDT_TFTP_SERVER * pTftpServer
);
/**
Send the next TFTP packet
@param [in] pTftpServer The TFTP server control structure address.
@param [in] pContext The context structure address.
@retval EFI_SUCCESS Message processed successfully
**/
EFI_STATUS
TftpTxPacket (
IN TSDT_TFTP_SERVER * pTftpServer,
IN TSDT_CONNECTION_CONTEXT * pContext
);
//------------------------------------------------------------------------------
#endif // _TFTP_SERVER_H_
|