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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_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 */
63int 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 */
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 */
117size_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 */
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 */
159struct 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 */
195int 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 */
239int 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 */
256int 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 */
269int 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 */
289int 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 */
301int 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 */
335int 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 */
352int 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 */
378int 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:3
signed long off_t
Definition stdint.h:8
__SIZE_TYPE__ size_t
Definition stdint.h:6
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" retur dest)
Definition string.h:151
int vasprintf(char **strp, const char *fmt, va_list args)
Write a formatted string to newly allocated memory.
Definition asprintf.c:18
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EPROTO
Protocol error.
Definition errno.h:625
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition interface.c:160
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition interface.c:84
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition interface.c:150
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition interface.c:118
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition interface.c:421
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
static void intf_temp_init(struct interface *intf, struct interface *original)
Initialise a temporary outbound-only object interface.
Definition interface.h:233
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition interface.h:293
#define intf_get_dest_op_no_passthru(intf, type, dest)
Get object interface destination and operation method (without pass-through)
Definition interface.h:258
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition interface.h:298
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition interface.h:282
#define INTF_FMT
printf() format string for INTF_DBG()
Definition interface.h:285
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition interface.h:307
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
unsigned long tmp
Definition linux_pci.h:65
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
int xfer_vreopen(struct interface *intf, int type, va_list args)
Reopen location.
Definition open.c:225
Data transfer interface opening.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define va_copy(dest, src)
Definition stdarg.h:11
#define va_end(ap)
Definition stdarg.h:10
#define va_start(ap, last)
Definition stdarg.h:8
__builtin_va_list va_list
Definition stdarg.h:7
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159
A persistent I/O buffer.
Definition iobuf.h:38
Data transfer metadata.
Definition xfer.h:23
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_vprintf(struct interface *intf, const char *format, va_list args)
Deliver formatted string.
Definition xfer.c:301
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
static struct xfer_metadata dummy_metadata
Dummy transfer metadata.
Definition xfer.c:47
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition xfer.c:239
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
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
int xfer_printf(struct interface *intf, const char *format,...)
Deliver formatted string.
Definition xfer.c:335
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
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
int xfer_vredirect(struct interface *intf, int type, va_list args)
Send redirection event.
Definition xfer.c:63
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition xfer.c:352
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(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition xfer.c:289
Data transfer interfaces.
#define xfer_vredirect_TYPE(object_type)
Definition xfer.h:70
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
#define xfer_alloc_iob_TYPE(object_type)
Definition xfer.h:83
#define xfer_window_TYPE(object_type)
Definition xfer.h:74
#define xfer_deliver_TYPE(object_type)
Definition xfer.h:89
int const char * format
Definition xfer.h:105