iPXE
xferbuf.c File Reference

Data transfer buffers. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/umalloc.h>
#include <ipxe/profile.h>
#include <ipxe/image.h>
#include <ipxe/xferbuf.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
void xferbuf_free (struct xfer_buffer *xferbuf)
 Free data transfer buffer.
static int xferbuf_ensure_size (struct xfer_buffer *xferbuf, size_t len)
 Ensure that data transfer buffer is large enough for the specified size.
int xferbuf_write (struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
 Write to data transfer buffer.
int xferbuf_read (struct xfer_buffer *xferbuf, size_t offset, void *data, size_t len)
 Read from data transfer buffer.
int xferbuf_deliver (struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Add received data to data transfer buffer.
static void * xferbuf_raw_access (struct xfer_buffer *xferbuf)
 Access raw pointer based data buffer.
static int xferbuf_malloc_realloc (struct xfer_buffer *xferbuf, size_t len)
 Reallocate malloc()-based data transfer buffer.
static int xferbuf_umalloc_realloc (struct xfer_buffer *xferbuf, size_t len)
 Reallocate umalloc()-based data transfer buffer.
static int xferbuf_fixed_realloc (struct xfer_buffer *xferbuf, size_t len)
 Reallocate fixed-size data transfer buffer.
static int xferbuf_void_realloc (struct xfer_buffer *xferbuf, size_t len __unused)
 Reallocate void data transfer buffer.
static int xferbuf_image_realloc (struct xfer_buffer *xferbuf, size_t len)
 Reallocate image-based data transfer buffer.
static void * xferbuf_image_access (struct xfer_buffer *xferbuf)
 Access image-based data transfer buffer.
struct xfer_buffer * xfer_buffer (struct interface *intf)
 Get underlying data transfer buffer.

Variables

static struct profiler xferbuf_deliver_profiler __profiler
 Data delivery profiler.
struct xfer_buffer_operations xferbuf_malloc_operations
 malloc()-based data buffer operations
struct xfer_buffer_operations xferbuf_umalloc_operations
 umalloc()-based data buffer operations
struct xfer_buffer_operations xferbuf_fixed_operations
 Fixed-size data buffer operations.
struct xfer_buffer_operations xferbuf_void_operations
 Void data buffer operations.
struct xfer_buffer_operations xferbuf_image_operations
 Image-based data buffer operations.

Detailed Description

Data transfer buffers.

Data transfer buffers provide an abstraction of an underlying storage buffer, with strictly bounds-checking accessors for reading and writing data and optional automatic resizing. They are designed primarily to act as the ultimate sink for receiving I/O buffers containing downloaded data, after all protocol-level framing has been stripped.

The underlying storage buffer may be backed by a malloc() allocation, a umalloc() allocation, a fixed-size buffer, a downloadable image's data, or a /dev/null-style void buffer.

Consumers of data buffers pass an offset and length when reading from or writing to the buffer. Any integer overflow will be reported as a failure (and no data will be read or written).

Attempting to read beyond the end of a buffer will always fail. Attempting to write beyond the end of a buffer will automatically attempt to resize the buffer to accommodate the write (and will fail if this cannot be done).

An object interface may choose to implement the xfer_buffer() interface method to provide another object with direct access to its own data buffer. This is something of a layering violation, but is required to support the badly designed PeerDist protocol which fails to provide the AES initialisation vector until after the encrypted data has all been received.

Definition in file xferbuf.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ xferbuf_free()

void xferbuf_free ( struct xfer_buffer * xferbuf)

Free data transfer buffer.

Parameters
xferbufData transfer buffer

Definition at line 88 of file xferbuf.c.

88 {
89
90 xferbuf->op->realloc ( xferbuf, 0 );
91 xferbuf->len = 0;
92 xferbuf->max = 0;
93 xferbuf->pos = 0;
94}
int(* realloc)(struct xfer_buffer *xferbuf, size_t len)
Reallocate data buffer.
Definition xferbuf.h:42
size_t len
Size of data.
Definition xferbuf.h:25
size_t max
Maximum required size of data.
Definition xferbuf.h:27
size_t pos
Current offset within data.
Definition xferbuf.h:29
struct xfer_buffer_operations * op
Data transfer buffer operations.
Definition xferbuf.h:31

References xfer_buffer::len, xfer_buffer::max, xfer_buffer::op, xfer_buffer::pos, and xfer_buffer_operations::realloc.

Referenced by peerblk_reset(), peermux_free(), validator_free(), and validator_xfer_close().

◆ xferbuf_ensure_size()

int xferbuf_ensure_size ( struct xfer_buffer * xferbuf,
size_t len )
static

Ensure that data transfer buffer is large enough for the specified size.

Parameters
xferbufData transfer buffer
lenRequired minimum size
Return values
rcReturn status code

Definition at line 103 of file xferbuf.c.

103 {
104 int rc;
105
106 /* Record maximum required size */
107 if ( len > xferbuf->max )
108 xferbuf->max = len;
109
110 /* If buffer is already large enough, do nothing */
112 return 0;
113
114 /* Extend buffer */
115 if ( ( rc = xferbuf->op->realloc ( xferbuf, len ) ) != 0 ) {
116 DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
117 "%zd bytes: %s\n", xferbuf, len, strerror ( rc ) );
118 return rc;
119 }
120 xferbuf->len = len;
121
122 return 0;
123}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:530
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References DBGC, len, xfer_buffer::len, xfer_buffer::max, xfer_buffer::op, rc, xfer_buffer_operations::realloc, and strerror().

Referenced by xferbuf_write().

◆ xferbuf_write()

int xferbuf_write ( struct xfer_buffer * xferbuf,
size_t offset,
const void * data,
size_t len )

Write to data transfer buffer.

Parameters
xferbufData transfer buffer
offsetStarting offset
dataData to write
lenLength of data

Definition at line 133 of file xferbuf.c.

134 {
135 size_t max_len;
136 void *raw;
137 int rc;
138
139 /* Check for overflow */
140 max_len = ( offset + len );
141 if ( max_len < offset )
142 return -EOVERFLOW;
143
144 /* Ensure buffer is large enough to contain this write */
145 if ( ( rc = xferbuf_ensure_size ( xferbuf, max_len ) ) != 0 )
146 return rc;
147
148 /* Copy data to buffer (if non-void) */
149 raw = xferbuf->op->access ( xferbuf );
150 profile_start ( &xferbuf_write_profiler );
151 if ( raw )
152 memcpy ( ( raw + offset ), data, len );
153 profile_stop ( &xferbuf_write_profiler );
154
155 return 0;
156}
__be32 raw[7]
Definition CIB_PRM.h:0
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define EOVERFLOW
Value too large to be stored in data type.
Definition errno.h:653
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition profile.h:174
static void profile_start(struct profiler *profiler)
Start profiling.
Definition profile.h:161
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void *(* access)(struct xfer_buffer *xferbuf)
Access data buffer.
Definition xferbuf.h:49
static int xferbuf_ensure_size(struct xfer_buffer *xferbuf, size_t len)
Ensure that data transfer buffer is large enough for the specified size.
Definition xferbuf.c:103

References xfer_buffer_operations::access, data, EOVERFLOW, len, memcpy(), offset, xfer_buffer::op, profile_start(), profile_stop(), raw, rc, and xferbuf_ensure_size().

Referenced by aoecmd_ata_rsp(), fcpcmd_recv_rddata(), iscsi_rx_data_in(), peerblk_decrypt_write(), peerblk_retrieval_rx(), usbblk_in_data(), and xferbuf_deliver().

◆ xferbuf_read()

int xferbuf_read ( struct xfer_buffer * xferbuf,
size_t offset,
void * data,
size_t len )

Read from data transfer buffer.

Parameters
xferbufData transfer buffer
offsetStarting offset
dataData to write
lenLength of data

Definition at line 166 of file xferbuf.c.

167 {
168 const void *raw;
169
170 /* Check that read is within buffer range */
171 if ( ( offset > xferbuf->len ) ||
172 ( len > ( xferbuf->len - offset ) ) )
173 return -ENOENT;
174
175 /* Access raw data buffer */
176 raw = xferbuf->op->access ( xferbuf );
177
178 /* Check that buffer is non-void */
179 if ( len && ( ! raw ) )
180 return -ENOTTY;
181
182 /* Copy data from buffer */
183 profile_start ( &xferbuf_read_profiler );
184 memcpy ( data, ( raw + offset ), len );
185 profile_stop ( &xferbuf_read_profiler );
186
187 return 0;
188}
#define ENOENT
No such file or directory.
Definition errno.h:558
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638

References xfer_buffer_operations::access, data, ENOENT, ENOTTY, len, xfer_buffer::len, memcpy(), offset, xfer_buffer::op, profile_start(), profile_stop(), and raw.

Referenced by aoecmd_ata_cmd(), fcpcmd_send_wrdata(), iscsi_tx_data_out(), peerblk_decrypt_read(), and usbblk_out_data().

◆ xferbuf_deliver()

int xferbuf_deliver ( struct xfer_buffer * xferbuf,
struct io_buffer * iobuf,
struct xfer_metadata * meta )

Add received data to data transfer buffer.

Parameters
xferbufData transfer buffer
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 198 of file xferbuf.c.

199 {
200 size_t len = iob_len ( iobuf );
201 size_t pos;
202 int rc;
203
204 /* Start profiling */
205 profile_start ( &xferbuf_deliver_profiler );
206
207 /* Calculate new buffer position */
208 pos = xferbuf->pos;
209 if ( meta->flags & XFER_FL_ABS_OFFSET )
210 pos = 0;
211 pos += meta->offset;
212
213 /* Write data to buffer */
214 if ( ( rc = xferbuf_write ( xferbuf, pos, iobuf->data, len ) ) != 0 )
215 goto done;
216
217 /* Update current buffer position */
218 xferbuf->pos = ( pos + len );
219
220 done:
221 free_iob ( iobuf );
222 profile_stop ( &xferbuf_deliver_profiler );
223 return rc;
224}
struct bofm_section_header done
Definition bofm_test.c:46
uint8_t meta
Metadata flags.
Definition ena.h:3
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
void * data
Start of data.
Definition iobuf.h:113
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
int xferbuf_write(struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
Write to data transfer buffer.
Definition xferbuf.c:133

References io_buffer::data, done, free_iob(), iob_len(), len, meta, xfer_buffer::pos, profile_start(), profile_stop(), rc, XFER_FL_ABS_OFFSET, and xferbuf_write().

Referenced by blktrans_deliver(), downloader_deliver(), efi_pxe_tftp_deliver(), peermux_info_deliver(), and validator_xfer_deliver().

◆ xferbuf_raw_access()

void * xferbuf_raw_access ( struct xfer_buffer * xferbuf)
static

Access raw pointer based data buffer.

Parameters
xferbufData transfer buffer
Return values
rawRaw data pointer

Definition at line 232 of file xferbuf.c.

232 {
233
234 return xferbuf->data;
235}
void * data
Data.
Definition xferbuf.h:23

References xfer_buffer::data.

◆ xferbuf_malloc_realloc()

int xferbuf_malloc_realloc ( struct xfer_buffer * xferbuf,
size_t len )
static

Reallocate malloc()-based data transfer buffer.

Parameters
xferbufData transfer buffer
lenNew length (or zero to free buffer)
Return values
rcReturn status code

Definition at line 244 of file xferbuf.c.

244 {
245 void *new_data;
246
247 new_data = realloc ( xferbuf->data, len );
248 if ( ! new_data )
249 return -ENOSPC;
250 xferbuf->data = new_data;
251 return 0;
252}
#define ENOSPC
No space left on device.
Definition errno.h:593
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:663

References xfer_buffer::data, ENOSPC, len, and realloc().

◆ xferbuf_umalloc_realloc()

int xferbuf_umalloc_realloc ( struct xfer_buffer * xferbuf,
size_t len )
static

Reallocate umalloc()-based data transfer buffer.

Parameters
xferbufData transfer buffer
lenNew length (or zero to free buffer)
Return values
rcReturn status code

Definition at line 267 of file xferbuf.c.

267 {
268 void *new_udata;
269
270 new_udata = urealloc ( xferbuf->data, len );
271 if ( ! new_udata )
272 return -ENOSPC;
273 xferbuf->data = new_udata;
274 return 0;
275}
void * urealloc(void *ptr, size_t new_size)
Reallocate external memory.

References xfer_buffer::data, ENOSPC, len, and urealloc().

◆ xferbuf_fixed_realloc()

int xferbuf_fixed_realloc ( struct xfer_buffer * xferbuf,
size_t len )
static

Reallocate fixed-size data transfer buffer.

Parameters
xferbufData transfer buffer
lenNew length (or zero to free buffer)
Return values
rcReturn status code

Definition at line 290 of file xferbuf.c.

290 {
291
292 /* Refuse to allocate extra space */
293 if ( len > xferbuf->len ) {
294 /* Note that EFI relies upon this error mapping to
295 * EFI_BUFFER_TOO_SMALL.
296 */
297 return -ERANGE;
298 }
299
300 return 0;
301}
#define ERANGE
Result too large.
Definition errno.h:683

References ERANGE, len, and xfer_buffer::len.

◆ xferbuf_void_realloc()

int xferbuf_void_realloc ( struct xfer_buffer * xferbuf,
size_t len __unused )
static

Reallocate void data transfer buffer.

Parameters
xferbufData transfer buffer
lenNew length (or zero to free buffer)
Return values
rcReturn status code

Definition at line 316 of file xferbuf.c.

317 {
318
319 /* Succeed without ever allocating data */
320 assert ( xferbuf->data == NULL );
321 return 0;
322}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61

References __unused, assert, xfer_buffer::data, len, and NULL.

◆ xferbuf_image_realloc()

int xferbuf_image_realloc ( struct xfer_buffer * xferbuf,
size_t len )
static

Reallocate image-based data transfer buffer.

Parameters
xferbufData transfer buffer
lenNew length (or zero to free buffer)
Return values
rcReturn status code

Definition at line 337 of file xferbuf.c.

337 {
338 struct image *image = xferbuf->data;
339 int rc;
340
341 /* Resize image */
342 if ( ( rc = image_set_len ( image, len ) ) != 0 )
343 return rc;
344
345 return 0;
346}
int image_set_len(struct image *image, size_t len)
Set image length.
Definition image.c:249
An executable image.
Definition image.h:24

References xfer_buffer::data, image_set_len(), len, and rc.

◆ xferbuf_image_access()

void * xferbuf_image_access ( struct xfer_buffer * xferbuf)
static

Access image-based data transfer buffer.

Parameters
xferbufData transfer buffer
Return values
rawRaw data pointer

Definition at line 354 of file xferbuf.c.

354 {
355 struct image *image = xferbuf->data;
356
357 return image->rwdata;
358}
void * rwdata
Writable data.
Definition image.h:53

References xfer_buffer::data, and image::rwdata.

◆ xfer_buffer()

struct xfer_buffer * xfer_buffer ( struct interface * intf)

Get underlying data transfer buffer.

Parameters
interfaceData transfer interface
Return values
xferbufData transfer buffer, or NULL on error

This call will check that the xfer_buffer() handler belongs to the destination interface which also provides xfer_deliver() for this interface.

This is done to prevent accidental accesses to a data transfer buffer which may be located behind a non-transparent datapath via a series of pass-through interfaces.

Definition at line 380 of file xferbuf.c.

380 {
381 struct interface *dest;
382 xfer_buffer_TYPE ( void * ) *op =
384 void *object = intf_object ( dest );
385 struct interface *xfer_deliver_dest;
386 struct xfer_buffer *xferbuf;
387
388 /* Check that this operation is provided by the same interface
389 * which handles xfer_deliver().
390 */
391 ( void ) intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest );
392
393 if ( op && ( dest == xfer_deliver_dest ) ) {
394 xferbuf = op ( object );
395 } else {
396 /* Default is to not have a data transfer buffer */
397 xferbuf = NULL;
398 }
399
400 intf_put ( xfer_deliver_dest );
401 intf_put ( dest );
402 return xferbuf;
403}
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
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition interface.c:160
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition interface.c:150
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159
A data transfer buffer.
Definition xferbuf.h:21
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
#define xfer_buffer_TYPE(object_type)
Definition xferbuf.h:138

References dest, interface::intf, intf_get_dest_op, intf_object(), intf_put(), NULL, op, xfer_buffer_TYPE, and xfer_deliver().

Referenced by http_content_buffer(), peerblk_decrypt(), and peermux_block_buffer().

Variable Documentation

◆ __profiler

struct profiler xferbuf_read_profiler __profiler
static
Initial value:
=
{ .name = "xferbuf.deliver" }

Data delivery profiler.

Data read profiler.

Data write profiler.

Definition at line 72 of file xferbuf.c.

72 { .name = "xferbuf.deliver" };

◆ xferbuf_malloc_operations

struct xfer_buffer_operations xferbuf_malloc_operations
Initial value:
= {
.access = xferbuf_raw_access,
}
static int xferbuf_malloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate malloc()-based data transfer buffer.
Definition xferbuf.c:244
static void * xferbuf_raw_access(struct xfer_buffer *xferbuf)
Access raw pointer based data buffer.
Definition xferbuf.c:232

malloc()-based data buffer operations

Definition at line 255 of file xferbuf.c.

255 {
256 .realloc = xferbuf_malloc_realloc,
257 .access = xferbuf_raw_access,
258};

Referenced by xferbuf_malloc_init().

◆ xferbuf_umalloc_operations

struct xfer_buffer_operations xferbuf_umalloc_operations
Initial value:
= {
.access = xferbuf_raw_access,
}
static int xferbuf_umalloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate umalloc()-based data transfer buffer.
Definition xferbuf.c:267

umalloc()-based data buffer operations

Definition at line 278 of file xferbuf.c.

278 {
279 .realloc = xferbuf_umalloc_realloc,
280 .access = xferbuf_raw_access,
281};

Referenced by xferbuf_umalloc_init().

◆ xferbuf_fixed_operations

struct xfer_buffer_operations xferbuf_fixed_operations
Initial value:
= {
.access = xferbuf_raw_access,
}
static int xferbuf_fixed_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate fixed-size data transfer buffer.
Definition xferbuf.c:290

Fixed-size data buffer operations.

Definition at line 304 of file xferbuf.c.

304 {
305 .realloc = xferbuf_fixed_realloc,
306 .access = xferbuf_raw_access,
307};

Referenced by xferbuf_fixed_init().

◆ xferbuf_void_operations

struct xfer_buffer_operations xferbuf_void_operations
Initial value:
= {
.access = xferbuf_raw_access,
}
static int xferbuf_void_realloc(struct xfer_buffer *xferbuf, size_t len __unused)
Reallocate void data transfer buffer.
Definition xferbuf.c:316

Void data buffer operations.

Definition at line 325 of file xferbuf.c.

325 {
326 .realloc = xferbuf_void_realloc,
327 .access = xferbuf_raw_access,
328};

Referenced by xferbuf_void_init().

◆ xferbuf_image_operations

struct xfer_buffer_operations xferbuf_image_operations
Initial value:
= {
}
static void * xferbuf_image_access(struct xfer_buffer *xferbuf)
Access image-based data transfer buffer.
Definition xferbuf.c:354
static int xferbuf_image_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate image-based data transfer buffer.
Definition xferbuf.c:337

Image-based data buffer operations.

Definition at line 361 of file xferbuf.c.

361 {
362 .realloc = xferbuf_image_realloc,
363 .access = xferbuf_image_access,
364};

Referenced by xferbuf_image_init().