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
20 FILE_LICENCE ( GPL2_OR_LATER );
26 #include <ipxe/iobuf.h>
27 #include <ipxe/xfer.h>
28 #include <ipxe/open.h>
32 * Data transfer interfaces
37 * Dummy transfer metadata
39 * This gets passed to xfer_interface::deliver() and equivalents when
40 * no metadata is available.
42 static struct xfer_metadata dummy_metadata;
44 /*****************************************************************************
46 * Data transfer interface operations
51 * Send redirection event
53 * @v intf Data transfer interface
54 * @v type New location type
55 * @v args Remaining arguments depend upon location type
56 * @ret rc Return status code
58 int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
59 struct interface tmp = INTF_INIT ( null_intf_desc );
60 struct interface *dest;
61 xfer_vredirect_TYPE ( void * ) *op =
62 intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest );
63 void *object = intf_object ( dest );
66 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
67 INTF_INTF_DBG ( intf, dest ) );
70 rc = op ( object, type, args );
72 /* Default is to reopen the interface as instructed,
73 * then send xfer_window_changed() messages to both
74 * new child and parent interfaces. Since our
75 * original child interface is likely to be closed and
76 * unplugged as a result of the call to
77 * xfer_vreopen(), we create a temporary interface in
78 * order to be able to send xfer_window_changed() to
81 intf_plug ( &tmp, dest );
82 rc = xfer_vreopen ( dest, type, args );
84 xfer_window_changed ( dest );
85 xfer_window_changed ( &tmp );
91 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
92 "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
101 * Check flow control window
103 * @v intf Data transfer interface
104 * @ret len Length of window
106 size_t xfer_window ( struct interface *intf ) {
107 struct interface *dest;
108 xfer_window_TYPE ( void * ) *op =
109 intf_get_dest_op ( intf, xfer_window, &dest );
110 void *object = intf_object ( dest );
116 /* Default is to provide an unlimited window */
117 len = ~( ( size_t ) 0 );
125 * Report change of flow control window
127 * @v intf Data transfer interface
129 * Note that this method is used to indicate only unsolicited changes
130 * in the flow control window. In particular, this method must not be
131 * called as part of the response to xfer_deliver(), since that could
132 * easily lead to an infinite loop. Callers of xfer_deliver() should
133 * assume that the flow control window will have changed without
134 * generating an xfer_window_changed() message.
136 void xfer_window_changed ( struct interface *intf ) {
137 struct interface *dest;
138 xfer_window_changed_TYPE ( void * ) *op =
139 intf_get_dest_op ( intf, xfer_window_changed, &dest );
140 void *object = intf_object ( dest );
145 /* Default is to do nothing */
152 * Allocate I/O buffer
154 * @v intf Data transfer interface
155 * @v len I/O buffer payload length
156 * @ret iobuf I/O buffer
158 struct io_buffer * xfer_alloc_iob ( struct interface *intf, size_t len ) {
159 struct interface *dest;
160 xfer_alloc_iob_TYPE ( void * ) *op =
161 intf_get_dest_op ( intf, xfer_alloc_iob, &dest );
162 void *object = intf_object ( dest );
163 struct io_buffer *iobuf;
165 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob %zd\n",
166 INTF_INTF_DBG ( intf, dest ), len );
169 iobuf = op ( object, len );
171 /* Default is to allocate an I/O buffer with no
174 iobuf = alloc_iob ( len );
178 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob "
179 "failed\n", INTF_INTF_DBG ( intf, dest ) );
189 * @v intf Data transfer interface
190 * @v iobuf Datagram I/O buffer
191 * @v meta Data transfer metadata
192 * @ret rc Return status code
194 int xfer_deliver ( struct interface *intf,
195 struct io_buffer *iobuf,
196 struct xfer_metadata *meta ) {
197 struct interface *dest;
198 xfer_deliver_TYPE ( void * ) *op =
199 intf_get_dest_op ( intf, xfer_deliver, &dest );
200 void *object = intf_object ( dest );
203 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
204 INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );
207 rc = op ( object, iobuf, meta );
209 /* Default is to discard the I/O buffer */
215 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
216 " deliver failed: %s\n",
217 INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
224 /*****************************************************************************
226 * Data transfer interface helper functions
231 * Send redirection event
233 * @v intf Data transfer interface
234 * @v type New location type
235 * @v ... Remaining arguments depend upon location type
236 * @ret rc Return status code
238 int xfer_redirect ( struct interface *intf, int type, ... ) {
242 va_start ( args, type );
243 rc = xfer_vredirect ( intf, type, args );
249 * Deliver datagram as I/O buffer without metadata
251 * @v intf Data transfer interface
252 * @v iobuf Datagram I/O buffer
253 * @ret rc Return status code
255 int xfer_deliver_iob ( struct interface *intf, struct io_buffer *iobuf ) {
256 return xfer_deliver ( intf, iobuf, &dummy_metadata );
260 * Deliver datagram as raw data
262 * @v intf Data transfer interface
264 * @v len Length of data
265 * @v meta Data transfer metadata
266 * @ret rc Return status code
268 int xfer_deliver_raw_meta ( struct interface *intf, const void *data,
269 size_t len, struct xfer_metadata *meta ) {
270 struct io_buffer *iobuf;
272 iobuf = xfer_alloc_iob ( intf, len );
276 memcpy ( iob_put ( iobuf, len ), data, len );
277 return xfer_deliver ( intf, iobuf, meta );
281 * Deliver datagram as raw data without metadata
283 * @v intf Data transfer interface
285 * @v len Length of data
286 * @ret rc Return status code
288 int xfer_deliver_raw ( struct interface *intf, const void *data, size_t len ) {
289 return xfer_deliver_raw_meta ( intf, data, len, &dummy_metadata );
293 * Deliver formatted string
295 * @v intf Data transfer interface
296 * @v format Format string
297 * @v args Arguments corresponding to the format string
298 * @ret rc Return status code
300 int xfer_vprintf ( struct interface *intf, const char *format,
307 /* Create temporary string */
308 va_copy ( args_tmp, args );
309 len = vasprintf ( &buf, format, args );
316 /* Transmit string */
317 if ( ( rc = xfer_deliver_raw ( intf, buf, len ) ) != 0 )
327 * Deliver formatted string
329 * @v intf Data transfer interface
330 * @v format Format string
331 * @v ... Arguments corresponding to the format string
332 * @ret rc Return status code
334 int xfer_printf ( struct interface *intf, const char *format, ... ) {
338 va_start ( args, format );
339 rc = xfer_vprintf ( intf, format, args );
347 * @v intf Data transfer interface
348 * @v offset Offset to new position
349 * @ret rc Return status code
351 int xfer_seek ( struct interface *intf, off_t offset ) {
352 struct io_buffer *iobuf;
353 struct xfer_metadata meta = {
354 .flags = XFER_FL_ABS_OFFSET,
358 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
359 INTF_DBG ( intf ), offset );
361 /* Allocate and send a zero-length data buffer */
362 iobuf = xfer_alloc_iob ( intf, 0 );
366 return xfer_deliver ( intf, iobuf, &meta );