Data Structures | |
| struct | s_PXENV_TFTP_READ |
| Parameter block for pxenv_tftp_read(). More... | |
Defines | |
| #define | PXENV_TFTP_READ 0x0022 |
| PXE API function code for pxenv_tftp_read(). | |
Typedefs | |
| typedef struct s_PXENV_TFTP_READ | PXENV_TFTP_READ_t |
Functions | |
| PXENV_EXIT_t | pxenv_tftp_read (struct s_PXENV_TFTP_READ *tftp_read) |
| TFTP READ. | |
| #define PXENV_TFTP_READ 0x0022 |
PXE API function code for pxenv_tftp_read().
Definition at line 636 of file pxe_api.h.
Referenced by pxe_api_call().
| typedef struct s_PXENV_TFTP_READ PXENV_TFTP_READ_t |
| PXENV_EXIT_t pxenv_tftp_read | ( | struct s_PXENV_TFTP_READ * | tftp_read | ) |
TFTP READ.
| tftp_read | Pointer to a struct s_PXENV_TFTP_READ | |
| s_PXENV_TFTP_READ::Buffer | Address of data buffer |
| PXENV_EXIT_SUCCESS | Data was read successfully | |
| PXENV_EXIT_FAILURE | Data was not read | |
| s_PXENV_TFTP_READ::Status | PXE status code | |
| s_PXENV_TFTP_READ::PacketNumber | TFTP packet number | |
| s_PXENV_TFTP_READ::BufferSize | Length of data written into buffer |
The buffer must be large enough to contain a packet of the size negotiated via the s_PXENV_TFTP_OPEN::PacketSize field in the pxenv_tftp_open() call. It is worth noting that the PXE specification does not require the caller to fill in s_PXENV_TFTP_READ::BufferSize before calling pxenv_tftp_read(), so the PXE stack is free to ignore whatever value the caller might place there and just assume that the buffer is large enough. That said, it may be worth the caller always filling in s_PXENV_TFTP_READ::BufferSize to guard against PXE stacks that mistake it for an input parameter.
The length of the TFTP data packet will be returned via s_PXENV_TFTP_READ::BufferSize. If this length is less than the blksize negotiated via s_PXENV_TFTP_OPEN::PacketSize in the call to pxenv_tftp_open(), this indicates that the block is the last block in the file. Note that zero is a valid length for s_PXENV_TFTP_READ::BufferSize, and will occur when the length of the file is a multiple of the blksize.
The PXE specification doesn't actually state that calls to pxenv_tftp_read() will return the data packets in strict sequential order, though most PXE stacks will probably do so. The sequence number of the packet will be returned in s_PXENV_TFTP_READ::PacketNumber. The first packet in the file has a sequence number of one, not zero.
To guard against flawed PXE stacks, the caller should probably set s_PXENV_TFTP_READ::PacketNumber to one less than the expected returned value (i.e. set it to zero for the first call to pxenv_tftp_read() and then re-use the returned s_PXENV_TFTP_READ parameter block for subsequent calls without modifying s_PXENV_TFTP_READ::PacketNumber between calls). The caller should also guard against potential problems caused by flawed implementations returning the occasional duplicate packet, by checking that the value returned in s_PXENV_TFTP_READ::PacketNumber is as expected (i.e. one greater than that returned from the previous call to pxenv_tftp_read()).
On x86, you must set the s_PXE::StatusCallout field to a nonzero value before calling this function in protected mode. You cannot call this function with a 32-bit stack segment. (See the relevant implementation note for more details.)
Definition at line 365 of file pxe_tftp.c.
References pxe_tftp_connection::blkidx, pxe_tftp_connection::blksize, pxe_tftp_connection::buffer, s_PXENV_TFTP_READ::Buffer, s_PXENV_TFTP_READ::BufferSize, DBG, EINPROGRESS, pxe_tftp_connection::offset, s_SEGOFF16::offset, s_PXENV_TFTP_READ::PacketNumber, PXENV_EXIT_FAILURE, PXENV_EXIT_SUCCESS, PXENV_STATUS, pxe_tftp_connection::rc, real_to_user(), s_SEGOFF16::segment, pxe_tftp_connection::size, pxe_tftp_connection::start, s_PXENV_TFTP_READ::Status, step(), and UNULL.
Referenced by pxe_api_call().
00365 { 00366 int rc; 00367 00368 DBG ( "PXENV_TFTP_READ to %04x:%04x", 00369 tftp_read->Buffer.segment, tftp_read->Buffer.offset ); 00370 00371 /* Read single block into buffer */ 00372 pxe_tftp.buffer = real_to_user ( tftp_read->Buffer.segment, 00373 tftp_read->Buffer.offset ); 00374 pxe_tftp.size = pxe_tftp.blksize; 00375 pxe_tftp.start = pxe_tftp.offset; 00376 while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) && 00377 ( pxe_tftp.offset == pxe_tftp.start ) ) 00378 step(); 00379 pxe_tftp.buffer = UNULL; 00380 tftp_read->BufferSize = ( pxe_tftp.offset - pxe_tftp.start ); 00381 tftp_read->PacketNumber = ++pxe_tftp.blkidx; 00382 00383 /* EINPROGRESS is normal if we haven't reached EOF yet */ 00384 if ( rc == -EINPROGRESS ) 00385 rc = 0; 00386 00387 tftp_read->Status = PXENV_STATUS ( rc ); 00388 return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS ); 00389 }
1.5.7.1