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 FILE_SECBOOT ( PERMITTED );
26 
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <ipxe/iobuf.h>
32 #include <ipxe/xfer.h>
33 #include <ipxe/open.h>
34 
35 /** @file
36  *
37  * Data transfer interfaces
38  *
39  */
40 
41 /**
42  * Dummy transfer metadata
43  *
44  * This gets passed to xfer_interface::deliver() and equivalents when
45  * no metadata is available.
46  */
48 
49 /*****************************************************************************
50  *
51  * Data transfer interface operations
52  *
53  */
54 
55 /**
56  * Send redirection event
57  *
58  * @v intf Data transfer interface
59  * @v type New location type
60  * @v args Remaining arguments depend upon location type
61  * @ret rc Return status code
62  */
63 int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
64  struct interface tmp;
65  struct interface *dest;
66  xfer_vredirect_TYPE ( void * ) *op =
68  void *object = intf_object ( dest );
69  int rc;
70 
71  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
72  INTF_INTF_DBG ( intf, dest ) );
73 
74  if ( op ) {
75  rc = op ( object, type, args );
76  } else {
77  /* Default is to reopen the interface as instructed,
78  * then send xfer_window_changed() messages to both
79  * new child and parent interfaces. Since our
80  * original child interface is likely to be closed and
81  * unplugged as a result of the call to
82  * xfer_vreopen(), we create a temporary interface in
83  * order to be able to send xfer_window_changed() to
84  * the parent.
85  *
86  * If redirection fails, then send intf_close() to the
87  * parent interface.
88  */
89  intf_temp_init ( &tmp, intf );
90  intf_plug ( &tmp, dest );
91  rc = xfer_vreopen ( dest, type, args );
92  if ( rc == 0 ) {
95  } else {
96  intf_close ( &tmp, rc );
97  }
98  intf_unplug ( &tmp );
99  }
100 
101  if ( rc != 0 ) {
102  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
103  "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
104  strerror ( rc ) );
105  }
106 
107  intf_put ( dest );
108  return rc;
109 }
110 
111 /**
112  * Check flow control window
113  *
114  * @v intf Data transfer interface
115  * @ret len Length of window
116  */
117 size_t xfer_window ( struct interface *intf ) {
118  struct interface *dest;
119  xfer_window_TYPE ( void * ) *op =
121  void *object = intf_object ( dest );
122  size_t len;
123 
124  if ( op ) {
125  len = op ( object );
126  } else {
127  /* Default is to provide an unlimited window */
128  len = ~( ( size_t ) 0 );
129  }
130 
131  intf_put ( dest );
132  return len;
133 }
134 
135 /**
136  * Report change of flow control window
137  *
138  * @v intf Data transfer interface
139  *
140  * Note that this method is used to indicate only unsolicited changes
141  * in the flow control window. In particular, this method must not be
142  * called as part of the response to xfer_deliver(), since that could
143  * easily lead to an infinite loop. Callers of xfer_deliver() should
144  * assume that the flow control window will have changed without
145  * generating an xfer_window_changed() message.
146  */
148 
150 }
151 
152 /**
153  * Allocate I/O buffer
154  *
155  * @v intf Data transfer interface
156  * @v len I/O buffer payload length
157  * @ret iobuf I/O buffer
158  */
159 struct io_buffer * xfer_alloc_iob ( struct interface *intf, size_t len ) {
160  struct interface *dest;
161  xfer_alloc_iob_TYPE ( void * ) *op =
163  void *object = intf_object ( dest );
164  struct io_buffer *iobuf;
165 
166  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob %zd\n",
167  INTF_INTF_DBG ( intf, dest ), len );
168 
169  if ( op ) {
170  iobuf = op ( object, len );
171  } else {
172  /* Default is to allocate an I/O buffer with no
173  * reserved space.
174  */
175  iobuf = alloc_iob ( len );
176  }
177 
178  if ( ! iobuf ) {
179  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob "
180  "failed\n", INTF_INTF_DBG ( intf, dest ) );
181  }
182 
183  intf_put ( dest );
184  return iobuf;
185 }
186 
187 /**
188  * Deliver datagram
189  *
190  * @v intf Data transfer interface
191  * @v iobuf Datagram I/O buffer
192  * @v meta Data transfer metadata
193  * @ret rc Return status code
194  */
195 int xfer_deliver ( struct interface *intf,
196  struct io_buffer *iobuf,
197  struct xfer_metadata *meta ) {
198  struct interface *dest;
199  xfer_deliver_TYPE ( void * ) *op =
201  void *object = intf_object ( dest );
202  int rc;
203 
204  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
205  INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );
206 
207  if ( op ) {
208  rc = op ( object, iobuf, meta );
209  } else {
210  /* Default is to discard the I/O buffer */
211  free_iob ( iobuf );
212  rc = -EPIPE;
213  }
214 
215  if ( rc != 0 ) {
216  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
217  " deliver failed: %s\n",
218  INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
219  }
220 
221  intf_put ( dest );
222  return rc;
223 }
224 
225 /*****************************************************************************
226  *
227  * Data transfer interface helper functions
228  *
229  */
230 
231 /**
232  * Send redirection event
233  *
234  * @v intf Data transfer interface
235  * @v type New location type
236  * @v ... Remaining arguments depend upon location type
237  * @ret rc Return status code
238  */
239 int xfer_redirect ( struct interface *intf, int type, ... ) {
240  va_list args;
241  int rc;
242 
243  va_start ( args, type );
244  rc = xfer_vredirect ( intf, type, args );
245  va_end ( args );
246  return rc;
247 }
248 
249 /**
250  * Deliver datagram as I/O buffer without metadata
251  *
252  * @v intf Data transfer interface
253  * @v iobuf Datagram I/O buffer
254  * @ret rc Return status code
255  */
256 int xfer_deliver_iob ( struct interface *intf, struct io_buffer *iobuf ) {
257  return xfer_deliver ( intf, iobuf, &dummy_metadata );
258 }
259 
260 /**
261  * Deliver datagram as raw data
262  *
263  * @v intf Data transfer interface
264  * @v data Data
265  * @v len Length of data
266  * @v meta Data transfer metadata
267  * @ret rc Return status code
268  */
269 int xfer_deliver_raw_meta ( struct interface *intf, const void *data,
270  size_t len, struct xfer_metadata *meta ) {
271  struct io_buffer *iobuf;
272 
273  iobuf = xfer_alloc_iob ( intf, len );
274  if ( ! iobuf )
275  return -ENOMEM;
276 
277  memcpy ( iob_put ( iobuf, len ), data, len );
278  return xfer_deliver ( intf, iobuf, meta );
279 }
280 
281 /**
282  * Deliver datagram as raw data without metadata
283  *
284  * @v intf Data transfer interface
285  * @v data Data
286  * @v len Length of data
287  * @ret rc Return status code
288  */
289 int xfer_deliver_raw ( struct interface *intf, const void *data, size_t len ) {
290  return xfer_deliver_raw_meta ( intf, data, len, &dummy_metadata );
291 }
292 
293 /**
294  * Deliver formatted string
295  *
296  * @v intf Data transfer interface
297  * @v format Format string
298  * @v args Arguments corresponding to the format string
299  * @ret rc Return status code
300  */
301 int xfer_vprintf ( struct interface *intf, const char *format,
302  va_list args ) {
303  va_list args_tmp;
304  char *buf;
305  int len;
306  int rc;
307 
308  /* Create temporary string */
309  va_copy ( args_tmp, args );
310  len = vasprintf ( &buf, format, args );
311  va_end ( args_tmp );
312  if ( len < 0 ) {
313  rc = len;
314  goto err_asprintf;
315  }
316 
317  /* Transmit string */
318  if ( ( rc = xfer_deliver_raw ( intf, buf, len ) ) != 0 )
319  goto err_deliver;
320 
321  err_deliver:
322  free ( buf );
323  err_asprintf:
324  return rc;
325 }
326 
327 /**
328  * Deliver formatted string
329  *
330  * @v intf Data transfer interface
331  * @v format Format string
332  * @v ... Arguments corresponding to the format string
333  * @ret rc Return status code
334  */
335 int xfer_printf ( struct interface *intf, const char *format, ... ) {
336  va_list args;
337  int rc;
338 
339  va_start ( args, format );
340  rc = xfer_vprintf ( intf, format, args );
341  va_end ( args );
342  return rc;
343 }
344 
345 /**
346  * Seek to position
347  *
348  * @v intf Data transfer interface
349  * @v offset Offset to new position
350  * @ret rc Return status code
351  */
352 int xfer_seek ( struct interface *intf, off_t offset ) {
353  struct io_buffer *iobuf;
354  struct xfer_metadata meta = {
355  .flags = XFER_FL_ABS_OFFSET,
356  .offset = offset,
357  };
358 
359  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
360  INTF_DBG ( intf ), offset );
361 
362  /* Allocate and send a zero-length data buffer */
363  iobuf = xfer_alloc_iob ( intf, 0 );
364  if ( ! iobuf )
365  return -ENOMEM;
366 
367  return xfer_deliver ( intf, iobuf, &meta );
368 }
369 
370 /**
371  * Check that data is delivered strictly in order
372  *
373  * @v meta Data transfer metadata
374  * @v pos Current position
375  * @v len Length of data
376  * @ret rc Return status code
377  */
378 int xfer_check_order ( struct xfer_metadata *meta, size_t *pos, size_t len ) {
379  size_t new_pos;
380 
381  /* Allow out-of-order zero-length packets (as used by xfer_seek()) */
382  if ( len == 0 )
383  return 0;
384 
385  /* Calculate position of this delivery */
386  new_pos = *pos;
387  if ( meta->flags & XFER_FL_ABS_OFFSET )
388  new_pos = 0;
389  new_pos += meta->offset;
390 
391  /* Fail if delivery position is not equal to current position */
392  if ( new_pos != *pos )
393  return -EPROTO;
394 
395  /* Update current position */
396  *pos += len;
397 
398  return 0;
399 }
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:147
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:298
#define iob_put(iobuf, len)
Definition: iobuf.h:125
#define va_end(ap)
Definition: stdarg.h:10
Data transfer metadata.
Definition: xfer.h:23
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:293
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:256
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:269
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:48
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:153
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition: interface.h:307
uint32_t type
Operating system type.
Definition: ena.h:12
#define EPIPE
Broken pipe.
Definition: errno.h:620
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:282
#define DBGC(...)
Definition: compiler.h:505
int xfer_vredirect(struct interface *intf, int type, va_list args)
Send redirection event.
Definition: xfer.c:63
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:159
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:378
#define va_copy(dest, src)
Definition: stdarg.h:11
#define xfer_vredirect_TYPE(object_type)
Definition: xfer.h:70
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:131
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:117
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:160
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition: xfer.c:289
#define xfer_deliver_TYPE(object_type)
Definition: xfer.h:89
Data transfer interfaces.
struct interface * intf
Original interface.
Definition: interface.h:159
unsigned long tmp
Definition: linux_pci.h:65
#define ENOMEM
Not enough space.
Definition: errno.h:535
FILE_SECBOOT(PERMITTED)
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An object interface.
Definition: interface.h:125
ring len
Length.
Definition: dwmac.h:231
int vasprintf(char **strp, const char *fmt, va_list args)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:18
#define EPROTO
Protocol error.
Definition: errno.h:625
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:118
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition: xfer.c:352
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
Data transfer interface opening.
#define xfer_window_TYPE(object_type)
Definition: xfer.h:74
int xfer_vprintf(struct interface *intf, const char *format, va_list args)
Deliver formatted string.
Definition: xfer.c:301
int xfer_vreopen(struct interface *intf, int type, va_list args)
Reopen location.
Definition: open.c:225
int xfer_printf(struct interface *intf, const char *format,...)
Deliver formatted string.
Definition: xfer.c:335
signed long off_t
Definition: stdint.h:8
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
__builtin_va_list va_list
Definition: stdarg.h:7
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:150
#define intf_get_dest_op_no_passthru(intf, type, dest)
Get object interface destination and operation method (without pass-through)
Definition: interface.h:258
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define xfer_alloc_iob_TYPE(object_type)
Definition: xfer.h:83
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
uint8_t meta
Metadata flags.
Definition: ena.h:14
#define va_start(ap, last)
Definition: stdarg.h:8
int const char * format
Definition: xfer.h:105
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:421
String functions.
static struct xfer_metadata dummy_metadata
Dummy transfer metadata.
Definition: xfer.c:47
static void intf_temp_init(struct interface *intf, struct interface *original)
Initialise a temporary outbound-only object interface.
Definition: interface.h:233
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:270
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition: interface.c:84
#define INTF_FMT
printf() format string for INTF_DBG()
Definition: interface.h:285
A persistent I/O buffer.
Definition: iobuf.h:38
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition: xfer.c:239