Browse Source

Separate out the documentation of the PXE API from the documentation of

the Etherboot implementation (i.e. don't do what Intel did).
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
572483cc59
2 changed files with 92 additions and 58 deletions
  1. 22
    0
      src/include/pxe_api.h
  2. 70
    58
      src/interface/pxe/pxe_udp.c

+ 22
- 0
src/include/pxe_api.h View File

1631
 
1631
 
1632
 /** @} */ /* pxe */
1632
 /** @} */ /* pxe */
1633
 
1633
 
1634
+/** @page pxe_notes Etherboot PXE implementation notes
1635
+
1636
+@section pxe_x86_modes x86 processor mode restrictions
1637
+
1638
+On the x86 platform, different PXE API calls have different
1639
+restrictions on the processor modes (real or protected) that can be
1640
+used.  See the individual API call descriptions for the restrictions
1641
+that apply to any particular call.
1642
+
1643
+@subsection pxe_x86_pmode16 Real mode, or protected-mode with 16-bit stack
1644
+
1645
+The PXE specification states that the API function can be called in
1646
+protected mode only if the s_PXE::StatusCallout field is set to a
1647
+non-zero value, and that the API function cannot be called with a
1648
+32-bit stack segment.
1649
+
1650
+Etherboot does not enforce either of these restrictions; they seem (as
1651
+with so much of the PXE specification) to be artifacts of the Intel
1652
+implementation.
1653
+
1654
+*/
1655
+
1634
 #endif /* PXE_API_H */
1656
 #endif /* PXE_API_H */

+ 70
- 58
src/interface/pxe/pxe_udp.c View File

43
  * pxenv_udp_read().  (If s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the
43
  * pxenv_udp_read().  (If s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the
44
  * local station's IP address will remain unchanged.)
44
  * local station's IP address will remain unchanged.)
45
  *
45
  *
46
- * You can have multiple UDP connections open simultaneously (and
47
- * even open concurrently with TFTP connections), provided that
46
+ * You can only have one open UDP connection at a time.  You cannot
47
+ * have a UDP connection open at the same time as a TFTP connection.
48
+ * (This is not strictly true for Etherboot; see the relevant @ref
49
+ * pxe_note_udp "implementation note" for more details.)
48
  *
50
  *
49
- *   - they all have the same local IP address, and
51
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
52
+ * value before calling this function in protected mode.  You cannot
53
+ * call this function with a 32-bit stack segment.  (See the relevant
54
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
50
  *
55
  *
51
- *   - you take the multiple connections into account when calling
52
- *     pxenv_udp_read().
53
- *
54
- * On x86, you can call pxenv_udp_open() in real mode, 16-bit
55
- * protected mode with a 16-bit stack segment, 16-bit protected mode
56
- * with a 32-bit stack segment, or V86 mode.  The pxe::StatusCallout
57
- * field may be zero even in protected mode.
58
- * 
59
- * @note The PXE specification states that you have only one UDP
60
- * connection open at a time, and that you cannot have a UDP
61
- * connection open simultaneously with a TFTP connection.  Etherboot
62
- * does not enforce this unnecessary restriction.
56
+ * @note The PXE specification does not make it clear whether the IP
57
+ * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only
58
+ * for this UDP connection, or retained for all future communication.
59
+ * The latter seems more consistent with typical PXE stack behaviour.
63
  *
60
  *
64
  */
61
  */
65
 PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *udp_open ) {
62
 PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *udp_open ) {
85
  * @ret s_PXENV_UDP_CLOSE::Status	PXE status code
82
  * @ret s_PXENV_UDP_CLOSE::Status	PXE status code
86
  * @err None				-
83
  * @err None				-
87
  *
84
  *
88
- * Closes a UDP "connection" opened with pxenv_udp_open().  Since UDP
89
- * is a connectionless protocol, this is a no-op.
90
- *
91
- * You can call pxenv_udp_close() even if there is another active UDP
92
- * or TFTP connection, since it has no effect on anything.
85
+ * Closes a UDP "connection" opened with pxenv_udp_open().
93
  *
86
  *
94
- * You can call pxenv_udp_close() in real mode, 16-bit protected mode
95
- * with a 16-bit stack segment, 16-bit protected mode with a 32-bit
96
- * stack segment, or V86 mode.  The pxe::StatusCallout field may be
97
- * zero even in protected mode.
87
+ * You can only have one open UDP connection at a time.  You cannot
88
+ * have a UDP connection open at the same time as a TFTP connection.
89
+ * You cannot use pxenv_udp_close() to close a TFTP connection; use
90
+ * pxenv_tftp_close() instead.  (This is not strictly true for
91
+ * Etherboot; see the relevant @ref pxe_note_udp "implementation note"
92
+ * for more details.)
98
  *
93
  *
99
- * @note The PXE specification states that you have only one UDP
100
- * connection open at a time, and that you cannot have a UDP
101
- * connection open simultaneously with a TFTP connection.  Etherboot
102
- * does not enforce this unnecessary restriction.
94
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
95
+ * value before calling this function in protected mode.  You cannot
96
+ * call this function with a 32-bit stack segment.  (See the relevant
97
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
103
  *
98
  *
104
  */
99
  */
105
 PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *udp_close __unused ) {
100
 PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *udp_close __unused ) {
119
  * @v s_PXENV_UDP_WRITE::buffer_size	Length of the UDP payload
114
  * @v s_PXENV_UDP_WRITE::buffer_size	Length of the UDP payload
120
  * @v s_PXENV_UDP_WRITE::buffer		Address of the UDP payload
115
  * @v s_PXENV_UDP_WRITE::buffer		Address of the UDP payload
121
  * @ret #PXENV_EXIT_SUCCESS		Packet was transmitted successfully
116
  * @ret #PXENV_EXIT_SUCCESS		Packet was transmitted successfully
122
- * @ret #PXENV_EXIT_FAILURE		Packet could not be transmitter
117
+ * @ret #PXENV_EXIT_FAILURE		Packet could not be transmitted
123
  * @ret s_PXENV_UDP_WRITE::Status	PXE status code
118
  * @ret s_PXENV_UDP_WRITE::Status	PXE status code
124
  * @err #PXENV_STATUS_UNDI_INVALID_STATE NIC could not be initialised
119
  * @err #PXENV_STATUS_UNDI_INVALID_STATE NIC could not be initialised
125
  * @err #PXENV_STATUS_OUT_OF_RESOURCES	Packet was too large to transmit
120
  * @err #PXENV_STATUS_OUT_OF_RESOURCES	Packet was too large to transmit
138
  *
133
  *
139
  * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
134
  * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
140
  *
135
  *
141
- * It is not necessary to call pxenv_udp_open() before using
142
- * pxenv_udp_write(), unless you want to change the local station's IP
143
- * address.  pxenv_udp_write() can be called even if there is another
144
- * active UDP or TFTP connection,.
145
- *
146
- * You can call pxenv_udp_write() in real mode, 16-bit protected mode
147
- * with a 16-bit stack segment, 16-bit protected mode with a 32-bit
148
- * stack segment, or V86 mode.  The pxe::StatusCallout field may be
149
- * zero even in protected mode.
136
+ * You must have opened a UDP connection with pxenv_udp_open() before
137
+ * calling pxenv_udp_write().  (This is not strictly true for
138
+ * Etherboot; see the relevant @ref pxe_note_udp "implementation note"
139
+ * for more details.)
150
  *
140
  *
151
- * @note The PXE specification states that you have only one UDP
152
- * connection open at a time, and that you cannot have a UDP
153
- * connection open simultaneously with a TFTP connection.  Etherboot
154
- * does not enforce this unnecessary restriction.
141
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
142
+ * value before calling this function in protected mode.  You cannot
143
+ * call this function with a 32-bit stack segment.  (See the relevant
144
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
155
  *
145
  *
156
  * @bug s_PXENV_UDP_WRITE::gw is ignored; the default routing table is
146
  * @bug s_PXENV_UDP_WRITE::gw is ignored; the default routing table is
157
  * always used.
147
  * always used.
278
  * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
268
  * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
279
  *
269
  *
280
  * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
270
  * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
281
- * any IP address will be accepted and may be returned.
271
+ * any IP address will be accepted and may be returned to the caller.
282
  *
272
  *
283
  * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
273
  * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
284
- * port will be accepted and may be returned.
274
+ * port will be accepted and may be returned to the caller.
285
  *
275
  *
286
- * It is not necessary to call pxenv_udp_open() before using
287
- * pxenv_udp_read().  pxenv_udp_read() can be called even if there is
288
- * another active UDP or TFTP connection, but be aware that you might
289
- * then receive (or cause to be lost) a packet belonging to another
290
- * connection.
276
+ * You must have opened a UDP connection with pxenv_udp_open() before
277
+ * calling pxenv_udp_read().  (This is not strictly true for
278
+ * Etherboot; see the relevant @ref pxe_note_udp "implementation note"
279
+ * for more details.)
291
  *
280
  *
292
- * You can call pxenv_udp_read() in real mode, 16-bit protected mode
293
- * with a 16-bit stack segment, 16-bit protected mode with a 32-bit
294
- * stack segment, or V86 mode.  The pxe::StatusCallout field may be
295
- * zero even in protected mode.
296
- *
297
- * @note The PXE specification states that you have only one UDP
298
- * connection open at a time, and that you cannot have a UDP
299
- * connection open simultaneously with a TFTP connection.  Etherboot
300
- * does not enforce this unnecessary restriction.
281
+ * On x86, you must set the s_PXE::StatusCallout field to a nonzero
282
+ * value before calling this function in protected mode.  You cannot
283
+ * call this function with a 32-bit stack segment.  (See the relevant
284
+ * @ref pxe_x86_pmode16 "implementation note" for more details.)
301
  *
285
  *
302
  * @note The PXE specification (version 2.1) does not state that we
286
  * @note The PXE specification (version 2.1) does not state that we
303
  * should fill in s_PXENV_UDP_READ::dest_ip and
287
  * should fill in s_PXENV_UDP_READ::dest_ip and
319
 	udp_read->Status = PXENV_STATUS_SUCCESS;
303
 	udp_read->Status = PXENV_STATUS_SUCCESS;
320
 	return PXENV_EXIT_SUCCESS;
304
 	return PXENV_EXIT_SUCCESS;
321
 }
305
 }
306
+
307
+/** @page pxe_notes PXE implementation notes
308
+
309
+@section pxe_note_udp The connectionless nature of UDP
310
+
311
+The PXE specification states that it is possible to have only one open
312
+UDP or TFTP connection at any one time.  Etherboot does not
313
+rigourously enforce this restriction, on the UNIX principle that the
314
+code should not prevent the user from doing stupid things, because
315
+that would also prevent the user from doing clever things.  Since UDP
316
+is a connectionless protocol, it is perfectly possible to have
317
+multiple concurrent UDP "connections" open, provided that you take the
318
+multiplicity of connections into account when calling
319
+pxenv_udp_read().  Similarly, there is no technical reason that
320
+prevents you from calling pxenv_udp_write() in the middle of a TFTP
321
+download.
322
+
323
+Etherboot will therefore never return error codes indicating "a
324
+connection is already open", such as #PXENV_STATUS_UDP_OPEN.  If you
325
+want to have multiple concurrent connections, go for it (but don't
326
+expect your perfectly sensible code to work with any other PXE stack).
327
+
328
+Since Etherboot treats UDP as the connectionless protocol that it
329
+really is, pxenv_udp_close() is actually a no-op, and there is no need
330
+to call pxenv_udp_open() before using pxenv_udp_write() or
331
+pxenv_udp_read().
332
+
333
+*/

Loading…
Cancel
Save