iPXE
xferbuf.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 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 (at your option) 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 <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <ipxe/xfer.h>
31#include <ipxe/iobuf.h>
32#include <ipxe/umalloc.h>
33#include <ipxe/profile.h>
34#include <ipxe/image.h>
35#include <ipxe/xferbuf.h>
36
37/** @file
38 *
39 * Data transfer buffer
40 *
41 */
42
43/** Data delivery profiler */
44static struct profiler xferbuf_deliver_profiler __profiler =
45 { .name = "xferbuf.deliver" };
46
47/** Data write profiler */
48static struct profiler xferbuf_write_profiler __profiler =
49 { .name = "xferbuf.write" };
50
51/** Data read profiler */
52static struct profiler xferbuf_read_profiler __profiler =
53 { .name = "xferbuf.read" };
54
55/**
56 * Free data transfer buffer
57 *
58 * @v xferbuf Data transfer buffer
59 */
60void xferbuf_free ( struct xfer_buffer *xferbuf ) {
61
62 xferbuf->op->realloc ( xferbuf, 0 );
63 xferbuf->len = 0;
64 xferbuf->max = 0;
65 xferbuf->pos = 0;
66}
67
68/**
69 * Ensure that data transfer buffer is large enough for the specified size
70 *
71 * @v xferbuf Data transfer buffer
72 * @v len Required minimum size
73 * @ret rc Return status code
74 */
75static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
76 int rc;
77
78 /* Record maximum required size */
79 if ( len > xferbuf->max )
80 xferbuf->max = len;
81
82 /* If buffer is already large enough, do nothing */
84 return 0;
85
86 /* Extend buffer */
87 if ( ( rc = xferbuf->op->realloc ( xferbuf, len ) ) != 0 ) {
88 DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
89 "%zd bytes: %s\n", xferbuf, len, strerror ( rc ) );
90 return rc;
91 }
92 xferbuf->len = len;
93
94 return 0;
95}
96
97/**
98 * Write to data transfer buffer
99 *
100 * @v xferbuf Data transfer buffer
101 * @v offset Starting offset
102 * @v data Data to write
103 * @v len Length of data
104 */
105int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
106 const void *data, size_t len ) {
107 size_t max_len;
108 void *raw;
109 int rc;
110
111 /* Check for overflow */
112 max_len = ( offset + len );
113 if ( max_len < offset )
114 return -EOVERFLOW;
115
116 /* Ensure buffer is large enough to contain this write */
117 if ( ( rc = xferbuf_ensure_size ( xferbuf, max_len ) ) != 0 )
118 return rc;
119
120 /* Copy data to buffer (if non-void) */
121 raw = xferbuf->op->access ( xferbuf );
122 profile_start ( &xferbuf_write_profiler );
123 if ( raw )
124 memcpy ( ( raw + offset ), data, len );
125 profile_stop ( &xferbuf_write_profiler );
126
127 return 0;
128}
129
130/**
131 * Read from data transfer buffer
132 *
133 * @v xferbuf Data transfer buffer
134 * @v offset Starting offset
135 * @v data Data to write
136 * @v len Length of data
137 */
138int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
139 void *data, size_t len ) {
140 const void *raw;
141
142 /* Check that read is within buffer range */
143 if ( ( offset > xferbuf->len ) ||
144 ( len > ( xferbuf->len - offset ) ) )
145 return -ENOENT;
146
147 /* Access raw data buffer */
148 raw = xferbuf->op->access ( xferbuf );
149
150 /* Check that buffer is non-void */
151 if ( len && ( ! raw ) )
152 return -ENOTTY;
153
154 /* Copy data from buffer */
155 profile_start ( &xferbuf_read_profiler );
156 memcpy ( data, ( raw + offset ), len );
157 profile_stop ( &xferbuf_read_profiler );
158
159 return 0;
160}
161
162/**
163 * Add received data to data transfer buffer
164 *
165 * @v xferbuf Data transfer buffer
166 * @v iobuf I/O buffer
167 * @v meta Data transfer metadata
168 * @ret rc Return status code
169 */
170int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
171 struct xfer_metadata *meta ) {
172 size_t len = iob_len ( iobuf );
173 size_t pos;
174 int rc;
175
176 /* Start profiling */
177 profile_start ( &xferbuf_deliver_profiler );
178
179 /* Calculate new buffer position */
180 pos = xferbuf->pos;
181 if ( meta->flags & XFER_FL_ABS_OFFSET )
182 pos = 0;
183 pos += meta->offset;
184
185 /* Write data to buffer */
186 if ( ( rc = xferbuf_write ( xferbuf, pos, iobuf->data, len ) ) != 0 )
187 goto done;
188
189 /* Update current buffer position */
190 xferbuf->pos = ( pos + len );
191
192 done:
193 free_iob ( iobuf );
194 profile_stop ( &xferbuf_deliver_profiler );
195 return rc;
196}
197
198/**
199 * Access raw pointer based data buffer
200 *
201 * @v xferbuf Data transfer buffer
202 * @ret raw Raw data pointer
203 */
204static void * xferbuf_raw_access ( struct xfer_buffer *xferbuf ) {
205
206 return xferbuf->data;
207}
208
209/**
210 * Reallocate malloc()-based data transfer buffer
211 *
212 * @v xferbuf Data transfer buffer
213 * @v len New length (or zero to free buffer)
214 * @ret rc Return status code
215 */
216static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
217 void *new_data;
218
219 new_data = realloc ( xferbuf->data, len );
220 if ( ! new_data )
221 return -ENOSPC;
222 xferbuf->data = new_data;
223 return 0;
224}
225
226/** malloc()-based data buffer operations */
231
232/**
233 * Reallocate umalloc()-based data transfer buffer
234 *
235 * @v xferbuf Data transfer buffer
236 * @v len New length (or zero to free buffer)
237 * @ret rc Return status code
238 */
239static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
240 void *new_udata;
241
242 new_udata = urealloc ( xferbuf->data, len );
243 if ( ! new_udata )
244 return -ENOSPC;
245 xferbuf->data = new_udata;
246 return 0;
247}
248
249/** umalloc()-based data buffer operations */
254
255/**
256 * Reallocate fixed-size data transfer buffer
257 *
258 * @v xferbuf Data transfer buffer
259 * @v len New length (or zero to free buffer)
260 * @ret rc Return status code
261 */
262static int xferbuf_fixed_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
263
264 /* Refuse to allocate extra space */
265 if ( len > xferbuf->len ) {
266 /* Note that EFI relies upon this error mapping to
267 * EFI_BUFFER_TOO_SMALL.
268 */
269 return -ERANGE;
270 }
271
272 return 0;
273}
274
275/** Fixed-size data buffer operations */
280
281/**
282 * Reallocate void data transfer buffer
283 *
284 * @v xferbuf Data transfer buffer
285 * @v len New length (or zero to free buffer)
286 * @ret rc Return status code
287 */
288static int xferbuf_void_realloc ( struct xfer_buffer *xferbuf,
289 size_t len __unused ) {
290
291 /* Succeed without ever allocating data */
292 assert ( xferbuf->data == NULL );
293 return 0;
294}
295
296/** Void data buffer operations */
301
302/**
303 * Reallocate image-based data transfer buffer
304 *
305 * @v xferbuf Data transfer buffer
306 * @v len New length (or zero to free buffer)
307 * @ret rc Return status code
308 */
309static int xferbuf_image_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
310 struct image *image = xferbuf->data;
311 int rc;
312
313 /* Resize image */
314 if ( ( rc = image_set_len ( image, len ) ) != 0 )
315 return rc;
316
317 return 0;
318}
319
320/**
321 * Access image-based data transfer buffer
322 *
323 * @v xferbuf Data transfer buffer
324 * @ret raw Raw data pointer
325 */
326static void * xferbuf_image_access ( struct xfer_buffer *xferbuf ) {
327 struct image *image = xferbuf->data;
328
329 return image->rwdata;
330}
331
332/** Image-based data buffer operations */
337
338/**
339 * Get underlying data transfer buffer
340 *
341 * @v interface Data transfer interface
342 * @ret xferbuf Data transfer buffer, or NULL on error
343 *
344 * This call will check that the xfer_buffer() handler belongs to the
345 * destination interface which also provides xfer_deliver() for this
346 * interface.
347 *
348 * This is done to prevent accidental accesses to a data transfer
349 * buffer which may be located behind a non-transparent datapath via a
350 * series of pass-through interfaces.
351 */
352struct xfer_buffer * xfer_buffer ( struct interface *intf ) {
353 struct interface *dest;
354 xfer_buffer_TYPE ( void * ) *op =
356 void *object = intf_object ( dest );
357 struct interface *xfer_deliver_dest;
358 struct xfer_buffer *xferbuf;
359
360 /* Check that this operation is provided by the same interface
361 * which handles xfer_deliver().
362 */
363 ( void ) intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest );
364
365 if ( op && ( dest == xfer_deliver_dest ) ) {
366 xferbuf = op ( object );
367 } else {
368 /* Default is to not have a data transfer buffer */
369 xferbuf = NULL;
370 }
371
372 intf_put ( xfer_deliver_dest );
373 intf_put ( dest );
374 return xferbuf;
375}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
__be32 raw[7]
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
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
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct bofm_section_header done
Definition bofm_test.c:46
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC(...)
Definition compiler.h:530
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ENOSPC
No space left on device.
Definition errno.h:550
#define EOVERFLOW
Value too large to be stored in data type.
Definition errno.h:610
#define ERANGE
Result too large.
Definition errno.h:640
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
int image_set_len(struct image *image, size_t len)
Set image length.
Definition image.c:249
Executable images.
Profiling.
#define __profiler
Declare a profiler.
Definition profile.h:61
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
User memory allocation.
void * urealloc(void *ptr, size_t new_size)
Reallocate external memory.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
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
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:607
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An executable image.
Definition image.h:24
void * rwdata
Writable data.
Definition image.h:53
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
void * data
Start of data.
Definition iobuf.h:53
A data structure for storing profiling information.
Definition profile.h:27
Data transfer buffer operations.
Definition xferbuf.h:35
int(* realloc)(struct xfer_buffer *xferbuf, size_t len)
Reallocate data buffer.
Definition xferbuf.h:42
void *(* access)(struct xfer_buffer *xferbuf)
Access data buffer.
Definition xferbuf.h:49
A data transfer buffer.
Definition xferbuf.h:21
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
void * data
Data.
Definition xferbuf.h:23
Data transfer metadata.
Definition xfer.h:23
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
Data transfer interfaces.
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
struct xfer_buffer_operations xferbuf_malloc_operations
malloc()-based data buffer operations
Definition xferbuf.c:227
struct xfer_buffer * xfer_buffer(struct interface *intf)
Get underlying data transfer buffer.
Definition xferbuf.c:352
static int xferbuf_void_realloc(struct xfer_buffer *xferbuf, size_t len __unused)
Reallocate void data transfer buffer.
Definition xferbuf.c:288
struct xfer_buffer_operations xferbuf_image_operations
Image-based data buffer operations.
Definition xferbuf.c:333
int xferbuf_read(struct xfer_buffer *xferbuf, size_t offset, void *data, size_t len)
Read from data transfer buffer.
Definition xferbuf.c:138
static int xferbuf_umalloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate umalloc()-based data transfer buffer.
Definition xferbuf.c:239
static int xferbuf_malloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate malloc()-based data transfer buffer.
Definition xferbuf.c:216
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:75
int xferbuf_write(struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
Write to data transfer buffer.
Definition xferbuf.c:105
struct xfer_buffer_operations xferbuf_void_operations
Void data buffer operations.
Definition xferbuf.c:297
static void * xferbuf_raw_access(struct xfer_buffer *xferbuf)
Access raw pointer based data buffer.
Definition xferbuf.c:204
void xferbuf_free(struct xfer_buffer *xferbuf)
Free data transfer buffer.
Definition xferbuf.c:60
static void * xferbuf_image_access(struct xfer_buffer *xferbuf)
Access image-based data transfer buffer.
Definition xferbuf.c:326
struct xfer_buffer_operations xferbuf_fixed_operations
Fixed-size data buffer operations.
Definition xferbuf.c:276
struct xfer_buffer_operations xferbuf_umalloc_operations
umalloc()-based data buffer operations
Definition xferbuf.c:250
int xferbuf_deliver(struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Add received data to data transfer buffer.
Definition xferbuf.c:170
static int xferbuf_fixed_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate fixed-size data transfer buffer.
Definition xferbuf.c:262
static int xferbuf_image_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate image-based data transfer buffer.
Definition xferbuf.c:309
Data transfer buffer.
#define xfer_buffer_TYPE(object_type)
Definition xferbuf.h:138