iPXE
xfer.c
Go to the documentation of this file.
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  * 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.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/open.h>
33 
34 /** @file
35  *
36  * Data transfer interfaces
37  *
38  */
39 
40 /**
41  * Dummy transfer metadata
42  *
43  * This gets passed to xfer_interface::deliver() and equivalents when
44  * no metadata is available.
45  */
47 
48 /*****************************************************************************
49  *
50  * Data transfer interface operations
51  *
52  */
53 
54 /**
55  * Send redirection event
56  *
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
61  */
62 int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
63  struct interface tmp;
64  struct interface *dest;
65  xfer_vredirect_TYPE ( void * ) *op =
67  void *object = intf_object ( dest );
68  int rc;
69 
70  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
71  INTF_INTF_DBG ( intf, dest ) );
72 
73  if ( op ) {
74  rc = op ( object, type, args );
75  } else {
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
83  * the parent.
84  *
85  * If redirection fails, then send intf_close() to the
86  * parent interface.
87  */
88  intf_temp_init ( &tmp, intf );
89  intf_plug ( &tmp, dest );
90  rc = xfer_vreopen ( dest, type, args );
91  if ( rc == 0 ) {
94  } else {
95  intf_close ( &tmp, rc );
96  }
97  intf_unplug ( &tmp );
98  }
99 
100  if ( rc != 0 ) {
101  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
102  "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
103  strerror ( rc ) );
104  }
105 
106  intf_put ( dest );
107  return rc;
108 }
109 
110 /**
111  * Check flow control window
112  *
113  * @v intf Data transfer interface
114  * @ret len Length of window
115  */
116 size_t xfer_window ( struct interface *intf ) {
117  struct interface *dest;
118  xfer_window_TYPE ( void * ) *op =
120  void *object = intf_object ( dest );
121  size_t len;
122 
123  if ( op ) {
124  len = op ( object );
125  } else {
126  /* Default is to provide an unlimited window */
127  len = ~( ( size_t ) 0 );
128  }
129 
130  intf_put ( dest );
131  return len;
132 }
133 
134 /**
135  * Report change of flow control window
136  *
137  * @v intf Data transfer interface
138  *
139  * Note that this method is used to indicate only unsolicited changes
140  * in the flow control window. In particular, this method must not be
141  * called as part of the response to xfer_deliver(), since that could
142  * easily lead to an infinite loop. Callers of xfer_deliver() should
143  * assume that the flow control window will have changed without
144  * generating an xfer_window_changed() message.
145  */
147 
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 =
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 =
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  va_end ( args_tmp );
311  if ( len < 0 ) {
312  rc = len;
313  goto err_asprintf;
314  }
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 }
368 
369 /**
370  * Check that data is delivered strictly in order
371  *
372  * @v meta Data transfer metadata
373  * @v pos Current position
374  * @v len Length of data
375  * @ret rc Return status code
376  */
377 int xfer_check_order ( struct xfer_metadata *meta, size_t *pos, size_t len ) {
378  size_t new_pos;
379 
380  /* Allow out-of-order zero-length packets (as used by xfer_seek()) */
381  if ( len == 0 )
382  return 0;
383 
384  /* Calculate position of this delivery */
385  new_pos = *pos;
386  if ( meta->flags & XFER_FL_ABS_OFFSET )
387  new_pos = 0;
388  new_pos += meta->offset;
389 
390  /* Fail if delivery position is not equal to current position */
391  if ( new_pos != *pos )
392  return -EPROTO;
393 
394  /* Update current position */
395  *pos += len;
396 
397  return 0;
398 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:146
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:297
#define iob_put(iobuf, len)
Definition: iobuf.h:120
#define va_end(ap)
Definition: stdarg.h:9
Data transfer metadata.
Definition: xfer.h:22
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:292
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:255
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition: xfer.c:268
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
Error codes.
__SIZE_TYPE__ size_t
Definition: stdint.h:6
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition: interface.h:306
#define EPIPE
Broken pipe.
Definition: errno.h:619
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:281
#define DBGC(...)
Definition: compiler.h:505
int xfer_vredirect(struct interface *intf, int type, va_list args)
Send redirection event.
Definition: xfer.c:62
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:158
int xfer_check_order(struct xfer_metadata *meta, size_t *pos, size_t len)
Check that data is delivered strictly in order.
Definition: xfer.c:377
#define va_copy(dest, src)
Definition: stdarg.h:10
#define xfer_vredirect_TYPE(object_type)
Definition: xfer.h:69
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:129
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:116
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:159
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition: xfer.c:288
#define xfer_deliver_TYPE(object_type)
Definition: xfer.h:88
Data transfer interfaces.
struct interface * intf
Original interface.
Definition: interface.h:158
unsigned long tmp
Definition: linux_pci.h:53
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An object interface.
Definition: interface.h:124
int vasprintf(char **strp, const char *fmt, va_list args)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:17
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static void * dest
Definition: strings.h:176
#define EPROTO
Protocol error.
Definition: errno.h:624
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:117
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition: xfer.c:351
int meta(WINDOW *, bool)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
Data transfer interface opening.
#define xfer_window_TYPE(object_type)
Definition: xfer.h:73
int xfer_vprintf(struct interface *intf, const char *format, va_list args)
Deliver formatted string.
Definition: xfer.c:300
int xfer_vreopen(struct interface *intf, int type, va_list args)
Reopen location.
Definition: open.c:224
int xfer_printf(struct interface *intf, const char *format,...)
Deliver formatted string.
Definition: xfer.c:334
signed long off_t
Definition: stdint.h:8
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
uint32_t len
Length.
Definition: ena.h:14
uint32_t type
Operating system type.
Definition: ena.h:12
__builtin_va_list va_list
Definition: stdarg.h:6
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:149
#define intf_get_dest_op_no_passthru(intf, type, dest)
Get object interface destination and operation method (without pass-through)
Definition: interface.h:257
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define xfer_alloc_iob_TYPE(object_type)
Definition: xfer.h:82
#define va_start(ap, last)
Definition: stdarg.h:7
int const char * format
Definition: xfer.h:104
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:420
String functions.
static struct xfer_metadata dummy_metadata
Dummy transfer metadata.
Definition: xfer.c:46
static void intf_temp_init(struct interface *intf, struct interface *original)
Initialise a temporary outbound-only object interface.
Definition: interface.h:232
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:269
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition: interface.c:83
#define INTF_FMT
printf() format string for INTF_DBG()
Definition: interface.h:284
A persistent I/O buffer.
Definition: iobuf.h:33
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition: xfer.c:238