8 * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or any later version.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 static int pxe_tftp_read_block ( unsigned char *data, unsigned int block,
28 unsigned int len, int eof );
33 * @v tftp_open Pointer to a struct s_PXENV_TFTP_OPEN
34 * @v s_PXENV_TFTP_OPEN::ServerIPAddress TFTP server IP address
35 * @v s_PXENV_TFTP_OPEN::GatewayIPAddress Relay agent IP address, or 0.0.0.0
36 * @v s_PXENV_TFTP_OPEN::FileName Name of file to open
37 * @v s_PXENV_TFTP_OPEN::TFTPPort TFTP server UDP port
38 * @v s_PXENV_TFTP_OPEN::PacketSize TFTP blksize option to request
39 * @ret #PXENV_EXIT_SUCCESS File was opened
40 * @ret #PXENV_EXIT_FAILURE File was not opened
41 * @ret s_PXENV_TFTP_OPEN::Status PXE status code
42 * @ret s_PXENV_TFTP_OPEN::PacketSize Negotiated blksize
43 * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Requested blksize too small
45 * Opens a TFTP connection for downloading a file a block at a time
46 * using pxenv_tftp_read().
48 * If s_PXENV_TFTP_OPEN::GatewayIPAddress is 0.0.0.0, normal IP
49 * routing will take place. See the relevant
50 * @ref pxe_routing "implementation note" for more details.
52 * The blksize negotiated with the TFTP server will be returned in
53 * s_PXENV_TFTP_OPEN::PacketSize, and will be the size of data blocks
54 * returned by subsequent calls to pxenv_tftp_read(). The TFTP server
55 * may negotiate a smaller blksize than the caller requested.
57 * Some TFTP servers do not support TFTP options, and will therefore
58 * not be able to use anything other than a fixed 512-byte blksize.
59 * The PXE specification version 2.1 requires that the caller must
60 * pass in s_PXENV_TFTP_OPEN::PacketSize with a value of 512 or
63 * You can only have one TFTP connection open at a time, because the
64 * PXE API requires the PXE stack to keep state (e.g. local and remote
65 * port numbers, data block index) about the open TFTP connection,
66 * rather than letting the caller do so.
68 * It is unclear precisely what constitutes a "TFTP open" operation.
69 * Clearly, we must send the TFTP open request to the server. Since
70 * we must know whether or not the open succeeded, we must wait for
71 * the first reply packet from the TFTP server. If the TFTP server
72 * supports options, the first reply packet will be an OACK; otherwise
73 * it will be a DATA packet. In other words, we may only get to
74 * discover whether or not the open succeeded when we receive the
75 * first block of data. However, the pxenv_tftp_open() API provides
76 * no way for us to return this block of data at this time. See the
77 * relevant @ref pxe_note_tftp "implementation note" for Etherboot's
78 * solution to this problem.
80 * On x86, you must set the s_PXE::StatusCallout field to a nonzero
81 * value before calling this function in protected mode. You cannot
82 * call this function with a 32-bit stack segment. (See the relevant
83 * @ref pxe_x86_pmode16 "implementation note" for more details.)
85 * @note If you pass in a value less than 512 for
86 * s_PXENV_TFTP_OPEN::PacketSize, Etherboot will attempt to negotiate
87 * this blksize with the TFTP server, even though such a value is not
88 * permitted according to the PXE specification. If the TFTP server
89 * ends up dictating a blksize larger than the value requested by the
90 * caller (which is very probable in the case of a requested blksize
91 * less than 512), then Etherboot will return the error
92 * #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE.
94 * @note According to the PXE specification version 2.1, this call
95 * "opens a file for reading/writing", though how writing is to be
96 * achieved without the existence of an API call %pxenv_tftp_write()
99 * @note Despite the existence of the numerous statements within the
100 * PXE specification of the form "...if a TFTP/MTFTP or UDP connection
101 * is active...", you cannot use pxenv_tftp_open() and
102 * pxenv_tftp_read() to read a file via MTFTP; only via plain old
103 * TFTP. If you want to use MTFTP, use pxenv_tftp_read_file()
104 * instead. Astute readers will note that, since
105 * pxenv_tftp_read_file() is an atomic operation from the point of
106 * view of the PXE API, it is conceptually impossible to issue any
107 * other PXE API call "if an MTFTP connection is active".
109 PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
110 struct sockaddr_in tftp_server;
111 struct tftpreq_info_t request;
112 struct tftpblk_info_t block;
114 DBG ( "PXENV_TFTP_OPEN" );
115 ENSURE_READY ( tftp_open );
117 /* Set server address and port */
118 tftp_server.sin_addr.s_addr = tftp_open->ServerIPAddress
119 ? tftp_open->ServerIPAddress
120 : arptable[ARP_SERVER].ipaddr.s_addr;
121 tftp_server.sin_port = ntohs ( tftp_open->TFTPPort );
122 #ifdef WORK_AROUND_BPBATCH_BUG
123 /* Force use of port 69; BpBatch tries to use port 4 for some
125 tftp_server.sin_port = TFTP_PORT;
127 /* Ignore gateway address; we can route properly */
128 /* Fill in request structure */
129 request.server = &tftp_server;
130 request.name = tftp_open->FileName;
131 request.blksize = tftp_open->PacketSize;
132 DBG ( " %@:%d/%s (%d)", tftp_open->ServerIPAddress,
133 tftp_open->TFTPPort, request.name, request.blksize );
134 if ( !request.blksize ) request.blksize = TFTP_DEFAULTSIZE_PACKET;
135 /* Make request and get first packet */
136 if ( !tftp_block ( &request, &block ) ) {
137 tftp_open->Status = PXENV_STATUS_TFTP_FILE_NOT_FOUND;
138 return PXENV_EXIT_FAILURE;
140 /* Fill in PacketSize */
141 tftp_open->PacketSize = request.blksize;
142 /* Store first block for later retrieval by TFTP_READ */
143 pxe_stack->tftpdata.magic_cookie = PXE_TFTP_MAGIC_COOKIE;
144 pxe_stack->tftpdata.len = block.len;
145 pxe_stack->tftpdata.eof = block.eof;
146 memcpy ( pxe_stack->tftpdata.data, block.data, block.len );
148 tftp_open->Status = PXENV_STATUS_SUCCESS;
149 return PXENV_EXIT_SUCCESS;
155 * @v tftp_close Pointer to a struct s_PXENV_TFTP_CLOSE
156 * @ret #PXENV_EXIT_SUCCESS File was closed successfully
157 * @ret #PXENV_EXIT_FAILURE File was not closed
158 * @ret s_PXENV_TFTP_CLOSE::Status PXE status code
161 * Close a connection previously opened with pxenv_tftp_open(). You
162 * must have previously opened a connection with pxenv_tftp_open().
164 * On x86, you must set the s_PXE::StatusCallout field to a nonzero
165 * value before calling this function in protected mode. You cannot
166 * call this function with a 32-bit stack segment. (See the relevant
167 * @ref pxe_x86_pmode16 "implementation note" for more details.)
169 * @note Since TFTP runs over UDP, which is a connectionless protocol,
170 * the concept of closing a file is somewhat meaningless. This call
171 * is a no-op for Etherboot.
173 PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
174 DBG ( "PXENV_TFTP_CLOSE" );
175 ENSURE_READY ( tftp_close );
176 tftp_close->Status = PXENV_STATUS_SUCCESS;
177 return PXENV_EXIT_SUCCESS;
183 * @v tftp_read Pointer to a struct s_PXENV_TFTP_READ
184 * @v s_PXENV_TFTP_READ::Buffer Address of data buffer
185 * @ret #PXENV_EXIT_SUCCESS Data was read successfully
186 * @ret #PXENV_EXIT_FAILURE Data was not read
187 * @ret s_PXENV_TFTP_READ::Status PXE status code
188 * @ret s_PXENV_TFTP_READ::PacketNumber TFTP packet number
189 * @ret s_PXENV_TFTP_READ::BufferSize Length of data written into buffer
191 * Reads a single packet from a connection previously opened with
192 * pxenv_tftp_open() into the data buffer pointed to by
193 * s_PXENV_TFTP_READ::Buffer. You must have previously opened a
194 * connection with pxenv_tftp_open(). The data written into
195 * s_PXENV_TFTP_READ::Buffer is just the file data; the various
196 * network headers have already been removed.
198 * The buffer must be large enough to contain a packet of the size
199 * negotiated via the s_PXENV_TFTP_OPEN::PacketSize field in the
200 * pxenv_tftp_open() call. It is worth noting that the PXE
201 * specification does @b not require the caller to fill in
202 * s_PXENV_TFTP_READ::BufferSize before calling pxenv_tftp_read(), so
203 * the PXE stack is free to ignore whatever value the caller might
204 * place there and just assume that the buffer is large enough. That
205 * said, it may be worth the caller always filling in
206 * s_PXENV_TFTP_READ::BufferSize to guard against PXE stacks that
207 * mistake it for an input parameter.
209 * The length of the TFTP data packet will be returned via
210 * s_PXENV_TFTP_READ::BufferSize. If this length is less than the
211 * blksize negotiated via s_PXENV_TFTP_OPEN::PacketSize in the call to
212 * pxenv_tftp_open(), this indicates that the block is the last block
213 * in the file. Note that zero is a valid length for
214 * s_PXENV_TFTP_READ::BufferSize, and will occur when the length of
215 * the file is a multiple of the blksize.
217 * The PXE specification doesn't actually state that calls to
218 * pxenv_tftp_read() will return the data packets in strict sequential
219 * order, though most PXE stacks will probably do so. The sequence
220 * number of the packet will be returned in
221 * s_PXENV_TFTP_READ::PacketNumber. The first packet in the file has
222 * a sequence number of one, not zero.
224 * To guard against flawed PXE stacks, the caller should probably set
225 * s_PXENV_TFTP_READ::PacketNumber to one less than the expected
226 * returned value (i.e. set it to zero for the first call to
227 * pxenv_tftp_read() and then re-use the returned s_PXENV_TFTP_READ
228 * parameter block for subsequent calls without modifying
229 * s_PXENV_TFTP_READ::PacketNumber between calls). The caller should
230 * also guard against potential problems caused by flawed
231 * implementations returning the occasional duplicate packet, by
232 * checking that the value returned in s_PXENV_TFTP_READ::PacketNumber
233 * is as expected (i.e. one greater than that returned from the
234 * previous call to pxenv_tftp_read()).
236 * Nothing in the PXE specification indicates when the TFTP
237 * acknowledgement packets will be sent back to the server. See the
238 * relevant @ref pxe_note_tftp "implementation note" for details on
239 * when Etherboot chooses to send these packets.
241 * On x86, you must set the s_PXE::StatusCallout field to a nonzero
242 * value before calling this function in protected mode. You cannot
243 * call this function with a 32-bit stack segment. (See the relevant
244 * @ref pxe_x86_pmode16 "implementation note" for more details.)
246 PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
247 struct tftpblk_info_t block;
249 DBG ( "PXENV_TFTP_READ" );
250 ENSURE_READY ( tftp_read );
252 /* Do we have a block pending */
253 if ( pxe_stack->tftpdata.magic_cookie == PXE_TFTP_MAGIC_COOKIE ) {
254 block.data = pxe_stack->tftpdata.data;
255 block.len = pxe_stack->tftpdata.len;
256 block.eof = pxe_stack->tftpdata.eof;
257 block.block = 1; /* Will be the first block */
258 pxe_stack->tftpdata.magic_cookie = 0;
260 if ( !tftp_block ( NULL, &block ) ) {
261 tftp_read->Status = PXENV_STATUS_TFTP_FILE_NOT_FOUND;
262 return PXENV_EXIT_FAILURE;
267 tftp_read->PacketNumber = block.block;
268 tftp_read->BufferSize = block.len;
269 memcpy ( SEGOFF16_TO_PTR(tftp_read->Buffer), block.data, block.len );
270 DBG ( " %d to %hx:%hx", block.len, tftp_read->Buffer.segment,
271 tftp_read->Buffer.offset );
273 tftp_read->Status = PXENV_STATUS_SUCCESS;
274 return PXENV_EXIT_SUCCESS;
278 * TFTP/MTFTP read file
280 * @v tftp_read_file Pointer to a struct s_PXENV_TFTP_READ_FILE
281 * @v s_PXENV_TFTP_READ_FILE::FileName File name
282 * @v s_PXENV_TFTP_READ_FILE::BufferSize Size of the receive buffer
283 * @v s_PXENV_TFTP_READ_FILE::Buffer Address of the receive buffer
284 * @v s_PXENV_TFTP_READ_FILE::ServerIPAddress TFTP server IP address
285 * @v s_PXENV_TFTP_READ_FILE::GatewayIPAddress Relay agent IP address
286 * @v s_PXENV_TFTP_READ_FILE::McastIPAddress File's multicast IP address
287 * @v s_PXENV_TFTP_READ_FILE::TFTPClntPort Client multicast UDP port
288 * @v s_PXENV_TFTP_READ_FILE::TFTPSrvPort Server multicast UDP port
289 * @v s_PXENV_TFTP_READ_FILE::TFTPOpenTimeOut Time to wait for first packet
290 * @v s_PXENV_TFTP_READ_FILE::TFTPReopenDelay MTFTP inactivity timeout
291 * @ret #PXENV_EXIT_SUCCESS File downloaded successfully
292 * @ret #PXENV_EXIT_FAILURE File not downloaded
293 * @ret s_PXENV_TFTP_READ_FILE::Status PXE status code
294 * @ret s_PXENV_TFTP_READ_FILE::BufferSize Length of downloaded file
296 * Downloads an entire file via either TFTP or MTFTP into the buffer
297 * pointed to by s_PXENV_TFTP_READ_FILE::Buffer.
299 * The PXE specification does not make it clear how the caller
300 * requests that MTFTP be used rather than TFTP (or vice versa). One
301 * reasonable guess is that setting
302 * s_PXENV_TFTP_READ_FILE::McastIPAddress to 0.0.0.0 would cause TFTP
303 * to be used instead of MTFTP, though it is conceivable that some PXE
304 * stacks would interpret that as "use the DHCP-provided multicast IP
305 * address" instead. Some PXE stacks will not implement MTFTP at all,
306 * and will always use TFTP.
308 * It is not specified whether or not
309 * s_PXENV_TFTP_READ_FILE::TFTPSrvPort will be used as the TFTP server
310 * port for TFTP (rather than MTFTP) downloads. Callers should assume
311 * that the only way to access a TFTP server on a non-standard port is
312 * to use pxenv_tftp_open() and pxenv_tftp_read().
314 * If s_PXENV_TFTP_READ_FILE::GatewayIPAddress is 0.0.0.0, normal IP
315 * routing will take place. See the relevant
316 * @ref pxe_routing "implementation note" for more details.
318 * It is interesting to note that s_PXENV_TFTP_READ_FILE::Buffer is an
319 * #ADDR32_t type, i.e. nominally a flat physical address. Some PXE
320 * NBPs (e.g. NTLDR) are known to call pxenv_tftp_read_file() in real
321 * mode with s_PXENV_TFTP_READ_FILE::Buffer set to an address above
322 * 1MB. This means that PXE stacks must be prepared to write to areas
323 * outside base memory. Exactly how this is to be achieved is not
324 * specified, though using INT 15,87 is as close to a standard method
325 * as any, and should probably be used. Switching to protected-mode
326 * in order to access high memory will fail if pxenv_tftp_read_file()
327 * is called in V86 mode; it is reasonably to expect that a V86
328 * monitor would intercept the relatively well-defined INT 15,87 if it
329 * wants the PXE stack to be able to write to high memory.
331 * Things get even more interesting if pxenv_tftp_read_file() is
332 * called in protected mode, because there is then absolutely no way
333 * for the PXE stack to write to an absolute physical address. You
334 * can't even get around the problem by creating a special "access
335 * everything" segment in the s_PXE data structure, because the
336 * #SEGDESC_t descriptors are limited to 64kB in size.
338 * Previous versions of the PXE specification (e.g. WfM 1.1a) provide
339 * a separate API call, %pxenv_tftp_read_file_pmode(), specifically to
340 * work around this problem. The s_PXENV_TFTP_READ_FILE_PMODE
341 * parameter block splits s_PXENV_TFTP_READ_FILE::Buffer into
342 * s_PXENV_TFTP_READ_FILE_PMODE::BufferSelector and
343 * s_PXENV_TFTP_READ_FILE_PMODE::BufferOffset, i.e. it provides a
344 * protected-mode segment:offset address for the data buffer. This
345 * API call is no longer present in version 2.1 of the PXE
348 * Etherboot makes the assumption that s_PXENV_TFTP_READ_FILE::Buffer
349 * is an offset relative to the caller's data segment, when
350 * pxenv_tftp_read_file() is called in protected mode.
352 * On x86, you must set the s_PXE::StatusCallout field to a nonzero
353 * value before calling this function in protected mode. You cannot
354 * call this function with a 32-bit stack segment. (See the relevant
355 * @ref pxe_x86_pmode16 "implementation note" for more details.)
357 * @note Microsoft's NTLDR assumes that the filename passed in via
358 * s_PXENV_TFTP_READ_FILE::FileName will be stored in the "file" field
359 * of the stored DHCPACK packet, whence it will be returned via any
360 * subsequent calls to pxenv_get_cached_info(). Though this is
361 * essentially a bug in the Intel PXE implementation (not, for once,
362 * in the specification!), it is a bug that Microsoft relies upon, and
363 * so we implement this bug-for-bug compatibility by overwriting the
364 * filename stored DHCPACK packet with the filename passed in
365 * s_PXENV_TFTP_READ_FILE::FileName.
368 PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
370 struct sockaddr_in tftp_server;
373 DBG ( "PXENV_TFTP_READ_FILE %s to [%x,%x)", tftp_read_file->FileName,
374 tftp_read_file->Buffer,
375 tftp_read_file->Buffer + tftp_read_file->BufferSize );
376 ENSURE_READY ( tftp_read_file );
378 /* inserted by Klaus Wittemeier */
379 /* KERNEL_BUF stores the name of the last required file */
380 /* This is a fix to make Microsoft Remote Install Services work (RIS) */
381 memcpy(KERNEL_BUF, tftp_read_file->FileName, sizeof(KERNEL_BUF));
382 /* end of insertion */
384 /* Set server address and port */
385 tftp_server.sin_addr.s_addr = tftp_read_file->ServerIPAddress
386 ? tftp_read_file->ServerIPAddress
387 : arptable[ARP_SERVER].ipaddr.s_addr;
388 tftp_server.sin_port = ntohs ( tftp_read_file->TFTPSrvPort );
390 pxe_stack->readfile.buffer = phys_to_virt ( tftp_read_file->Buffer );
391 pxe_stack->readfile.bufferlen = tftp_read_file->BufferSize;
392 pxe_stack->readfile.offset = 0;
394 rc = tftp ( NULL, &tftp_server, tftp_read_file->FileName,
395 pxe_tftp_read_block );
397 tftp_read_file->Status = PXENV_STATUS_FAILURE;
398 return PXENV_EXIT_FAILURE;
400 tftp_read_file->Status = PXENV_STATUS_SUCCESS;
401 return PXENV_EXIT_SUCCESS;
404 static int pxe_tftp_read_block ( unsigned char *data,
405 unsigned int block __unused,
406 unsigned int len, int eof ) {
407 if ( pxe_stack->readfile.buffer ) {
408 if ( pxe_stack->readfile.offset + len >=
409 pxe_stack->readfile.bufferlen ) return -1;
410 memcpy ( pxe_stack->readfile.buffer +
411 pxe_stack->readfile.offset, data, len );
413 pxe_stack->readfile.offset += len;
420 * @v tftp_get_fsize Pointer to a struct s_PXENV_TFTP_GET_FSIZE
421 * @v s_PXENV_TFTP_GET_FSIZE::ServerIPAddress TFTP server IP address
422 * @v s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress Relay agent IP address
423 * @v s_PXENV_TFTP_GET_FSIZE::FileName File name
424 * @ret #PXENV_EXIT_SUCCESS File size was determined successfully
425 * @ret #PXENV_EXIT_FAILURE File size was not determined
426 * @ret s_PXENV_TFTP_GET_FSIZE::Status PXE status code
427 * @ret s_PXENV_TFTP_GET_FSIZE::FileSize File size
429 * Determine the size of a file on a TFTP server. This uses the
430 * "tsize" TFTP option, and so will not work with a TFTP server that
431 * does not support TFTP options, or that does not support the "tsize"
434 * The PXE specification states that this API call will @b not open a
435 * TFTP connection for subsequent use with pxenv_tftp_read(). (This
436 * is somewhat daft, since the only way to obtain the file size via
437 * the "tsize" option involves issuing a TFTP open request, but that's
440 * You cannot call pxenv_tftp_get_fsize() while a TFTP or UDP
441 * connection is open.
443 * If s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress is 0.0.0.0, normal IP
444 * routing will take place. See the relevant
445 * @ref pxe_routing "implementation note" for more details.
447 * On x86, you must set the s_PXE::StatusCallout field to a nonzero
448 * value before calling this function in protected mode. You cannot
449 * call this function with a 32-bit stack segment. (See the relevant
450 * @ref pxe_x86_pmode16 "implementation note" for more details.)
452 * @note There is no way to specify the TFTP server port with this API
453 * call. Though you can open a file using a non-standard TFTP server
454 * port (via s_PXENV_TFTP_OPEN::TFTPPort or, potentially,
455 * s_PXENV_TFTP_READ_FILE::TFTPSrvPort), you can only get the size of
456 * a file from a TFTP server listening on the standard TFTP port.
457 * "Consistency" is not a word in Intel's vocabulary.
459 PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
463 DBG ( "PXENV_TFTP_GET_FSIZE" );
464 ENSURE_READY ( tftp_get_fsize );
466 pxe_stack->readfile.buffer = NULL;
467 pxe_stack->readfile.bufferlen = 0;
468 pxe_stack->readfile.offset = 0;
470 #warning "Rewrite pxenv_tftp_get_fsize, please"
472 tftp_get_fsize->FileSize = 0;
473 tftp_get_fsize->Status = PXENV_STATUS_FAILURE;
474 return PXENV_EXIT_FAILURE;
476 tftp_get_fsize->FileSize = pxe_stack->readfile.offset;
477 tftp_get_fsize->Status = PXENV_STATUS_SUCCESS;
478 return PXENV_EXIT_SUCCESS;
481 /** @page pxe_notes Etherboot PXE implementation notes
483 @section pxe_note_tftp Welding together the TFTP protocol and the PXE TFTP API
485 The PXE TFTP API is fundamentally poorly designed; the TFTP protocol
486 simply does not map well into "open file", "read file block", "close
487 file" operations. The problem is the unreliable nature of UDP
488 transmissions and the lock-step mechanism employed by TFTP to
489 guarantee file transfer. The lock-step mechanism requires that if we
490 time out waiting for a packet to arrive, we must trigger its
491 retransmission by retransmitting our own previously transmitted
494 For example, suppose that pxenv_tftp_read() is called to read the
495 first data block of a file from a server that does not support TFTP
496 options, and that no data block is received within the timeout period.
497 In order to trigger the retransmission of this data block,
498 pxenv_tftp_read() must retransmit the TFTP open request. However, the
499 information used to build the TFTP open request is not available at
500 this time; it was provided only to the pxenv_tftp_open() call. Even
501 if we were able to retransmit a TFTP open request, we would have to
502 allocate a new local port number (and be prepared for data to arrive
503 from a new remote port number) in order to avoid violating the TFTP
504 protocol specification.
506 The question of when to transmit the ACK packets is also awkward. At
507 a first glance, it would seem to be fairly simple: acknowledge a
508 packet immediately after receiving it. However, since the ACK packet
509 may itself be lost, the next call to pxenv_tftp_read() must be
510 prepared to retransmit the acknowledgement.
512 Another problem to consider is that the pxenv_tftp_open() API call
513 must return an indication of whether or not the TFTP open request
514 succeeded. In the case of a TFTP server that doesn't support TFTP
515 options, the only indication of a successful open is the reception of
516 the first data block. However, the pxenv_tftp_open() API provides no
517 way to return this data block at this time.
519 At least some PXE stacks (e.g. NILO) solve this problem by violating
520 the TFTP protocol and never bothering with retransmissions, relying on
521 the TFTP server to retransmit when it times out waiting for an ACK.
522 This approach is dubious at best; if, for example, the initial TFTP
523 open request is lost then NILO will believe that it has opened the
524 file and will eventually time out and give up while waiting for the
525 first packet to arrive.
527 The only viable solution seems to be to allocate a buffer for the
528 storage of the first data packet returned by the TFTP server, since we
529 may receive this packet during the pxenv_tftp_open() call but have to
530 return it from the subsequent pxenv_tftp_read() call. This buffer
531 must be statically allocated and must be dedicated to providing a
532 temporary home for TFTP packets. There is nothing in the PXE
533 specification that prevents a caller from calling
534 e.g. pxenv_undi_transmit() between calls to the TFTP API, so we cannot
535 use the normal transmit/receive buffer for this purpose.
537 Having paid the storage penalty for this buffer, we can then gain some
538 simplicity by exploiting it in full. There is at least one
539 circumstance (pxenv_tftp_open() called to open a file on a server that
540 does not support TFTP options) in which we will have to enter
541 pxenv_tftp_read() knowing that our previous transmission (the open
542 request, in this situation) has already been acknowledged.
543 Implementation of pxenv_tftp_read() can be made simpler by making this
544 condition an invariant. Specifically, on each call to
545 pxenv_tftp_read(), we shall ensure that the following are true:
547 - Our previous transmission has already been acknowledged. We
548 therefore do not need to keep state about our previous
551 - The next packet to read is already in a buffer in memory.
553 In order to maintain these two conditions, pxenv_tftp_read() must do
556 - Copy the data packet from our buffer to the caller's buffer.
558 - Acknowledge the data packet that we have just copied. This will
559 trigger transmission of the next packet from the server.
561 - Retransmit this acknowledgement packet until the next packet
564 - Copy the packet into our internal buffer, ready for the next call
565 to pxenv_tftp_read().
567 It can be verified that this preserves the invariant condition, and it
568 is clear that the resulting implementation of pxenv_tftp_read() can be
569 relatively simple. (For the special case of the last data packet,
570 pxenv_tftp_read() should return immediately after sending a single
571 acknowledgement packet.)
573 In order to set up this invariant condition for the first call to
574 pxenv_tftp_read(), pxenv_tftp_open() must do the following:
576 - Construct and transmit the TFTP open request.
578 - Retransmit the TFTP open request (using a new local port number as
579 necessary) until a response (DATA, OACK, or ERROR) is received.
581 - If the response is an OACK, acknowledge the OACK and retransmit
582 the acknowledgement until the first DATA packet arrives.
584 - If we have a DATA packet, store it in a buffer ready for the first
585 call to pxenv_tftp_read().
587 This approach has the advantage of being fully compliant with both
588 RFC1350 (TFTP) and RFC2347 (TFTP options). It avoids unnecessary
589 retransmissions. The cost is approximately 1500 bytes of
590 uninitialised storage. Since there is demonstrably no way to avoid
591 paying this cost without either violating the protocol specifications
592 or introducing unnecessary retransmissions, we deem this to be a cost
595 A small performance gain may be obtained by adding a single extra
596 "send ACK" in both pxenv_tftp_open() and pxenv_tftp_read() immediately
597 after receiving the DATA packet and copying it into the internal
598 buffer. The sequence of events for pxenv_tftp_read() then becomes:
600 - Copy the data packet from our buffer to the caller's buffer.
602 - If this was the last data packet, return immediately.
604 - Check to see if a TFTP data packet is waiting. If not, send an
605 ACK for the data packet that we have just copied, and retransmit
606 this ACK until the next data packet arrives.
608 - Copy the packet into our internal buffer, ready for the next call
609 to pxenv_tftp_read().
611 - Send a single ACK for this data packet.
613 Sending the ACK at this point allows the server to transmit the next
614 data block while our caller is processing the current packet. If this
615 ACK is lost, or the DATA packet it triggers is lost or is consumed by
616 something other than pxenv_tftp_read() (e.g. by calls to
617 pxenv_undi_isr()), then the next call to pxenv_tftp_read() will not
618 find a TFTP data packet waiting and will retransmit the ACK anyway.
620 Note to future API designers at Intel: try to understand the
621 underlying network protocol first!