Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / core / xfer.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <ipxe/iobuf.h>
27 #include <ipxe/xfer.h>
28 #include <ipxe/open.h>
29
30 /** @file
31  *
32  * Data transfer interfaces
33  *
34  */
35
36 /**
37  * Dummy transfer metadata
38  *
39  * This gets passed to xfer_interface::deliver() and equivalents when
40  * no metadata is available.
41  */
42 static struct xfer_metadata dummy_metadata;
43
44 /*****************************************************************************
45  *
46  * Data transfer interface operations
47  *
48  */
49
50 /**
51  * Send redirection event
52  *
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
57  */
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 );
64         int rc;
65
66         DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
67                INTF_INTF_DBG ( intf, dest ) );
68
69         if ( op ) {
70                 rc = op ( object, type, args );
71         } else {
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
79                  * the parent.
80                  */
81                 intf_plug ( &tmp, dest );
82                 rc = xfer_vreopen ( dest, type, args );
83                 if ( rc == 0 ) {
84                         xfer_window_changed ( dest );
85                         xfer_window_changed ( &tmp );
86                 }
87                 intf_unplug ( &tmp );
88         }
89
90         if ( rc != 0 ) {
91                 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
92                        "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
93                        strerror ( rc ) );
94         }
95
96         intf_put ( dest );
97         return rc;
98 }
99
100 /**
101  * Check flow control window
102  *
103  * @v intf              Data transfer interface
104  * @ret len             Length of window
105  */
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 );
111         size_t len;
112
113         if ( op ) {
114                 len = op ( object );
115         } else {
116                 /* Default is to provide an unlimited window */
117                 len = ~( ( size_t ) 0 );
118         }
119
120         intf_put ( dest );
121         return len;
122 }
123
124 /**
125  * Report change of flow control window
126  *
127  * @v intf              Data transfer interface
128  *
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.
135  */
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 );
141
142         if ( op ) {
143                 op ( object );
144         } else {
145                 /* Default is to do nothing */
146         }
147
148         intf_put ( dest );
149 }
150
151 /**
152  * Allocate I/O buffer
153  *
154  * @v intf              Data transfer interface
155  * @v len               I/O buffer payload length
156  * @ret iobuf           I/O buffer
157  */
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;
164
165         DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob %zd\n",
166                INTF_INTF_DBG ( intf, dest ), len );
167
168         if ( op ) {
169                 iobuf = op ( object, len );
170         } else {
171                 /* Default is to allocate an I/O buffer with no
172                  * reserved space.
173                  */
174                 iobuf = alloc_iob ( len );
175         }
176
177         if ( ! iobuf ) {
178                 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob "
179                        "failed\n", INTF_INTF_DBG ( intf, dest ) );
180         }
181
182         intf_put ( dest );
183         return iobuf;
184 }
185
186 /**
187  * Deliver datagram
188  *
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
193  */
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 );
201         int rc;
202
203         DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
204                INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );
205
206         if ( op ) {
207                 rc = op ( object, iobuf, meta );
208         } else {
209                 /* Default is to discard the I/O buffer */
210                 free_iob ( iobuf );
211                 rc = -EPIPE;
212         }
213
214         if ( rc != 0 ) {
215                 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
216                        " deliver failed: %s\n",
217                        INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
218         }
219
220         intf_put ( dest );
221         return rc;
222 }
223
224 /*****************************************************************************
225  *
226  * Data transfer interface helper functions
227  *
228  */
229
230 /**
231  * Send redirection event
232  *
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
237  */
238 int xfer_redirect ( struct interface *intf, int type, ... ) {
239         va_list args;
240         int rc;
241
242         va_start ( args, type );
243         rc = xfer_vredirect ( intf, type, args );
244         va_end ( args );
245         return rc;
246 }
247
248 /**
249  * Deliver datagram as I/O buffer without metadata
250  *
251  * @v intf              Data transfer interface
252  * @v iobuf             Datagram I/O buffer
253  * @ret rc              Return status code
254  */
255 int xfer_deliver_iob ( struct interface *intf, struct io_buffer *iobuf ) {
256         return xfer_deliver ( intf, iobuf, &dummy_metadata );
257 }
258
259 /**
260  * Deliver datagram as raw data
261  *
262  * @v intf              Data transfer interface
263  * @v data              Data
264  * @v len               Length of data
265  * @v meta              Data transfer metadata
266  * @ret rc              Return status code
267  */
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;
271
272         iobuf = xfer_alloc_iob ( intf, len );
273         if ( ! iobuf )
274                 return -ENOMEM;
275
276         memcpy ( iob_put ( iobuf, len ), data, len );
277         return xfer_deliver ( intf, iobuf, meta );
278 }
279
280 /**
281  * Deliver datagram as raw data without metadata
282  *
283  * @v intf              Data transfer interface
284  * @v data              Data
285  * @v len               Length of data
286  * @ret rc              Return status code
287  */
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 );
290 }
291
292 /**
293  * Deliver formatted string
294  *
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
299  */
300 int xfer_vprintf ( struct interface *intf, const char *format,
301                    va_list args ) {
302         va_list args_tmp;
303         char *buf;
304         int len;
305         int rc;
306
307         /* Create temporary string */
308         va_copy ( args_tmp, args );
309         len = vasprintf ( &buf, format, args );
310         if ( len < 0 ) {
311                 rc = len;
312                 goto err_asprintf;
313         }
314         va_end ( args_tmp );
315
316         /* Transmit string */
317         if ( ( rc = xfer_deliver_raw ( intf, buf, len ) ) != 0 )
318                 goto err_deliver;
319
320  err_deliver:
321         free ( buf );
322  err_asprintf:
323         return rc;
324 }
325
326 /**
327  * Deliver formatted string
328  *
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
333  */
334 int xfer_printf ( struct interface *intf, const char *format, ... ) {
335         va_list args;
336         int rc;
337
338         va_start ( args, format );
339         rc = xfer_vprintf ( intf, format, args );
340         va_end ( args );
341         return rc;
342 }
343
344 /**
345  * Seek to position
346  *
347  * @v intf              Data transfer interface
348  * @v offset            Offset to new position
349  * @ret rc              Return status code
350  */
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,
355                 .offset = offset,
356         };
357
358         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
359                INTF_DBG ( intf ), offset );
360
361         /* Allocate and send a zero-length data buffer */
362         iobuf = xfer_alloc_iob ( intf, 0 );
363         if ( ! iobuf )
364                 return -ENOMEM;
365
366         return xfer_deliver ( intf, iobuf, &meta );
367 }