Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

pxe_tftp.c 27KB

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