2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
30 #include <ipxe/iobuf.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/open.h>
36 * Data transfer interfaces
41 * Dummy transfer metadata
43 * This gets passed to xfer_interface::deliver() and equivalents when
44 * no metadata is available.
46 static struct xfer_metadata dummy_metadata
;
48 /*****************************************************************************
50 * Data transfer interface operations
55 * Send redirection event
57 * @v intf Data transfer interface
58 * @v type New location type
59 * @v args Remaining arguments depend upon location type
60 * @ret rc Return status code
62 int xfer_vredirect ( struct interface
*intf
, int type
, va_list args
) {
63 struct interface tmp
= INTF_INIT ( null_intf_desc
);
64 struct interface
*dest
;
65 xfer_vredirect_TYPE ( void * ) *op
=
66 intf_get_dest_op_no_passthru ( intf
, xfer_vredirect
, &dest
);
67 void *object
= intf_object ( dest
);
70 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" redirect\n",
71 INTF_INTF_DBG ( intf
, dest
) );
74 rc
= op ( object
, type
, args
);
76 /* Default is to reopen the interface as instructed,
77 * then send xfer_window_changed() messages to both
78 * new child and parent interfaces. Since our
79 * original child interface is likely to be closed and
80 * unplugged as a result of the call to
81 * xfer_vreopen(), we create a temporary interface in
82 * order to be able to send xfer_window_changed() to
85 intf_plug ( &tmp
, dest
);
86 rc
= xfer_vreopen ( dest
, type
, args
);
88 xfer_window_changed ( dest
);
89 xfer_window_changed ( &tmp
);
95 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" redirect "
96 "failed: %s\n", INTF_INTF_DBG ( intf
, dest
),
105 * Check flow control window
107 * @v intf Data transfer interface
108 * @ret len Length of window
110 size_t xfer_window ( struct interface
*intf
) {
111 struct interface
*dest
;
112 xfer_window_TYPE ( void * ) *op
=
113 intf_get_dest_op ( intf
, xfer_window
, &dest
);
114 void *object
= intf_object ( dest
);
120 /* Default is to provide an unlimited window */
121 len
= ~( ( size_t ) 0 );
129 * Report change of flow control window
131 * @v intf Data transfer interface
133 * Note that this method is used to indicate only unsolicited changes
134 * in the flow control window. In particular, this method must not be
135 * called as part of the response to xfer_deliver(), since that could
136 * easily lead to an infinite loop. Callers of xfer_deliver() should
137 * assume that the flow control window will have changed without
138 * generating an xfer_window_changed() message.
140 void xfer_window_changed ( struct interface
*intf
) {
142 intf_poke ( intf
, xfer_window_changed
);
146 * Allocate I/O buffer
148 * @v intf Data transfer interface
149 * @v len I/O buffer payload length
150 * @ret iobuf I/O buffer
152 struct io_buffer
* xfer_alloc_iob ( struct interface
*intf
, size_t len
) {
153 struct interface
*dest
;
154 xfer_alloc_iob_TYPE ( void * ) *op
=
155 intf_get_dest_op ( intf
, xfer_alloc_iob
, &dest
);
156 void *object
= intf_object ( dest
);
157 struct io_buffer
*iobuf
;
159 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" alloc_iob %zd\n",
160 INTF_INTF_DBG ( intf
, dest
), len
);
163 iobuf
= op ( object
, len
);
165 /* Default is to allocate an I/O buffer with no
168 iobuf
= alloc_iob ( len
);
172 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" alloc_iob "
173 "failed\n", INTF_INTF_DBG ( intf
, dest
) );
183 * @v intf Data transfer interface
184 * @v iobuf Datagram I/O buffer
185 * @v meta Data transfer metadata
186 * @ret rc Return status code
188 int xfer_deliver ( struct interface
*intf
,
189 struct io_buffer
*iobuf
,
190 struct xfer_metadata
*meta
) {
191 struct interface
*dest
;
192 xfer_deliver_TYPE ( void * ) *op
=
193 intf_get_dest_op ( intf
, xfer_deliver
, &dest
);
194 void *object
= intf_object ( dest
);
197 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" deliver %zd\n",
198 INTF_INTF_DBG ( intf
, dest
), iob_len ( iobuf
) );
201 rc
= op ( object
, iobuf
, meta
);
203 /* Default is to discard the I/O buffer */
209 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
210 " deliver failed: %s\n",
211 INTF_INTF_DBG ( intf
, dest
), strerror ( rc
) );
218 /*****************************************************************************
220 * Data transfer interface helper functions
225 * Send redirection event
227 * @v intf Data transfer interface
228 * @v type New location type
229 * @v ... Remaining arguments depend upon location type
230 * @ret rc Return status code
232 int xfer_redirect ( struct interface
*intf
, int type
, ... ) {
236 va_start ( args
, type
);
237 rc
= xfer_vredirect ( intf
, type
, args
);
243 * Deliver datagram as I/O buffer without metadata
245 * @v intf Data transfer interface
246 * @v iobuf Datagram I/O buffer
247 * @ret rc Return status code
249 int xfer_deliver_iob ( struct interface
*intf
, struct io_buffer
*iobuf
) {
250 return xfer_deliver ( intf
, iobuf
, &dummy_metadata
);
254 * Deliver datagram as raw data
256 * @v intf Data transfer interface
258 * @v len Length of data
259 * @v meta Data transfer metadata
260 * @ret rc Return status code
262 int xfer_deliver_raw_meta ( struct interface
*intf
, const void *data
,
263 size_t len
, struct xfer_metadata
*meta
) {
264 struct io_buffer
*iobuf
;
266 iobuf
= xfer_alloc_iob ( intf
, len
);
270 memcpy ( iob_put ( iobuf
, len
), data
, len
);
271 return xfer_deliver ( intf
, iobuf
, meta
);
275 * Deliver datagram as raw data without metadata
277 * @v intf Data transfer interface
279 * @v len Length of data
280 * @ret rc Return status code
282 int xfer_deliver_raw ( struct interface
*intf
, const void *data
, size_t len
) {
283 return xfer_deliver_raw_meta ( intf
, data
, len
, &dummy_metadata
);
287 * Deliver formatted string
289 * @v intf Data transfer interface
290 * @v format Format string
291 * @v args Arguments corresponding to the format string
292 * @ret rc Return status code
294 int xfer_vprintf ( struct interface
*intf
, const char *format
,
301 /* Create temporary string */
302 va_copy ( args_tmp
, args
);
303 len
= vasprintf ( &buf
, format
, args
);
310 /* Transmit string */
311 if ( ( rc
= xfer_deliver_raw ( intf
, buf
, len
) ) != 0 )
321 * Deliver formatted string
323 * @v intf Data transfer interface
324 * @v format Format string
325 * @v ... Arguments corresponding to the format string
326 * @ret rc Return status code
328 int xfer_printf ( struct interface
*intf
, const char *format
, ... ) {
332 va_start ( args
, format
);
333 rc
= xfer_vprintf ( intf
, format
, args
);
341 * @v intf Data transfer interface
342 * @v offset Offset to new position
343 * @ret rc Return status code
345 int xfer_seek ( struct interface
*intf
, off_t offset
) {
346 struct io_buffer
*iobuf
;
347 struct xfer_metadata meta
= {
348 .flags
= XFER_FL_ABS_OFFSET
,
352 DBGC ( INTF_COL ( intf
), "INTF " INTF_FMT
" seek to %ld\n",
353 INTF_DBG ( intf
), offset
);
355 /* Allocate and send a zero-length data buffer */
356 iobuf
= xfer_alloc_iob ( intf
, 0 );
360 return xfer_deliver ( intf
, iobuf
, &meta
);
364 * Check that data is delivered strictly in order
366 * @v meta Data transfer metadata
367 * @v pos Current position
368 * @v len Length of data
369 * @ret rc Return status code
371 int xfer_check_order ( struct xfer_metadata
*meta
, size_t *pos
, size_t len
) {
374 /* Allow out-of-order zero-length packets (as used by xfer_seek()) */
378 /* Calculate position of this delivery */
380 if ( meta
->flags
& XFER_FL_ABS_OFFSET
)
382 new_pos
+= meta
->offset
;
384 /* Fail if delivery position is not equal to current position */
385 if ( new_pos
!= *pos
)
388 /* Update current position */