You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pxe_tftp.c 27KB

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