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/xferbuf.h>
35
36/** @file
37 *
38 * Data transfer buffer
39 *
40 */
41
42/** Data delivery profiler */
43static struct profiler xferbuf_deliver_profiler __profiler =
44 { .name = "xferbuf.deliver" };
45
46/** Data write profiler */
47static struct profiler xferbuf_write_profiler __profiler =
48 { .name = "xferbuf.write" };
49
50/** Data read profiler */
51static struct profiler xferbuf_read_profiler __profiler =
52 { .name = "xferbuf.read" };
53
54/**
55 * Detach data from data transfer buffer
56 *
57 * @v xferbuf Data transfer buffer
58 *
59 * The caller assumes responsibility for eventually freeing the data
60 * previously owned by the data transfer buffer.
61 */
62void xferbuf_detach ( struct xfer_buffer *xferbuf ) {
63
64 xferbuf->data = NULL;
65 xferbuf->len = 0;
66 xferbuf->max = 0;
67 xferbuf->pos = 0;
68}
69
70/**
71 * Free data transfer buffer
72 *
73 * @v xferbuf Data transfer buffer
74 */
75void xferbuf_free ( struct xfer_buffer *xferbuf ) {
76
77 xferbuf->op->realloc ( xferbuf, 0 );
78 xferbuf_detach ( xferbuf );
79}
80
81/**
82 * Ensure that data transfer buffer is large enough for the specified size
83 *
84 * @v xferbuf Data transfer buffer
85 * @v len Required minimum size
86 * @ret rc Return status code
87 */
88static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
89 int rc;
90
91 /* Record maximum required size */
92 if ( len > xferbuf->max )
93 xferbuf->max = len;
94
95 /* If buffer is already large enough, do nothing */
97 return 0;
98
99 /* Extend buffer */
100 if ( ( rc = xferbuf->op->realloc ( xferbuf, len ) ) != 0 ) {
101 DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
102 "%zd bytes: %s\n", xferbuf, len, strerror ( rc ) );
103 return rc;
104 }
105 xferbuf->len = len;
106
107 return 0;
108}
109
110/**
111 * Write to data transfer buffer
112 *
113 * @v xferbuf Data transfer buffer
114 * @v offset Starting offset
115 * @v data Data to write
116 * @v len Length of data
117 */
118int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
119 const void *data, size_t len ) {
120 size_t max_len;
121 int rc;
122
123 /* Check for overflow */
124 max_len = ( offset + len );
125 if ( max_len < offset )
126 return -EOVERFLOW;
127
128 /* Ensure buffer is large enough to contain this write */
129 if ( ( rc = xferbuf_ensure_size ( xferbuf, max_len ) ) != 0 )
130 return rc;
131
132 /* Copy data to buffer (if non-void) */
133 profile_start ( &xferbuf_write_profiler );
134 if ( xferbuf->data )
135 memcpy ( ( xferbuf->data + offset ), data, len );
136 profile_stop ( &xferbuf_write_profiler );
137
138 return 0;
139}
140
141/**
142 * Read from data transfer buffer
143 *
144 * @v xferbuf Data transfer buffer
145 * @v offset Starting offset
146 * @v data Data to write
147 * @v len Length of data
148 */
149int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
150 void *data, size_t len ) {
151
152 /* Check that read is within buffer range */
153 if ( ( offset > xferbuf->len ) ||
154 ( len > ( xferbuf->len - offset ) ) )
155 return -ENOENT;
156
157 /* Check that buffer is non-void */
158 if ( len && ( ! xferbuf->data ) )
159 return -ENOTTY;
160
161 /* Copy data from buffer */
162 profile_start ( &xferbuf_read_profiler );
163 memcpy ( data, ( xferbuf->data + offset ), len );
164 profile_stop ( &xferbuf_read_profiler );
165
166 return 0;
167}
168
169/**
170 * Add received data to data transfer buffer
171 *
172 * @v xferbuf Data transfer buffer
173 * @v iobuf I/O buffer
174 * @v meta Data transfer metadata
175 * @ret rc Return status code
176 */
177int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
178 struct xfer_metadata *meta ) {
179 size_t len = iob_len ( iobuf );
180 size_t pos;
181 int rc;
182
183 /* Start profiling */
184 profile_start ( &xferbuf_deliver_profiler );
185
186 /* Calculate new buffer position */
187 pos = xferbuf->pos;
188 if ( meta->flags & XFER_FL_ABS_OFFSET )
189 pos = 0;
190 pos += meta->offset;
191
192 /* Write data to buffer */
193 if ( ( rc = xferbuf_write ( xferbuf, pos, iobuf->data, len ) ) != 0 )
194 goto done;
195
196 /* Update current buffer position */
197 xferbuf->pos = ( pos + len );
198
199 done:
200 free_iob ( iobuf );
201 profile_stop ( &xferbuf_deliver_profiler );
202 return rc;
203}
204
205/**
206 * Reallocate malloc()-based data transfer buffer
207 *
208 * @v xferbuf Data transfer buffer
209 * @v len New length (or zero to free buffer)
210 * @ret rc Return status code
211 */
212static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
213 void *new_data;
214
215 new_data = realloc ( xferbuf->data, len );
216 if ( ! new_data )
217 return -ENOSPC;
218 xferbuf->data = new_data;
219 return 0;
220}
221
222/** malloc()-based data buffer operations */
226
227/**
228 * Reallocate umalloc()-based data transfer buffer
229 *
230 * @v xferbuf Data transfer buffer
231 * @v len New length (or zero to free buffer)
232 * @ret rc Return status code
233 */
234static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
235 void *new_udata;
236
237 new_udata = urealloc ( xferbuf->data, len );
238 if ( ! new_udata )
239 return -ENOSPC;
240 xferbuf->data = new_udata;
241 return 0;
242}
243
244/** umalloc()-based data buffer operations */
248
249/**
250 * Reallocate fixed-size data transfer buffer
251 *
252 * @v xferbuf Data transfer buffer
253 * @v len New length (or zero to free buffer)
254 * @ret rc Return status code
255 */
256static int xferbuf_fixed_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
257
258 /* Refuse to allocate extra space */
259 if ( len > xferbuf->len ) {
260 /* Note that EFI relies upon this error mapping to
261 * EFI_BUFFER_TOO_SMALL.
262 */
263 return -ERANGE;
264 }
265
266 return 0;
267}
268
269/** Fixed-size data buffer operations */
273
274/**
275 * Reallocate void data transfer buffer
276 *
277 * @v xferbuf Data transfer buffer
278 * @v len New length (or zero to free buffer)
279 * @ret rc Return status code
280 */
281static int xferbuf_void_realloc ( struct xfer_buffer *xferbuf,
282 size_t len __unused ) {
283
284 /* Succeed without ever allocating data */
285 assert ( xferbuf->data == NULL );
286 return 0;
287}
288
289/** Void data buffer operations */
293
294/**
295 * Get underlying data transfer buffer
296 *
297 * @v interface Data transfer interface
298 * @ret xferbuf Data transfer buffer, or NULL on error
299 *
300 * This call will check that the xfer_buffer() handler belongs to the
301 * destination interface which also provides xfer_deliver() for this
302 * interface.
303 *
304 * This is done to prevent accidental accesses to a data transfer
305 * buffer which may be located behind a non-transparent datapath via a
306 * series of pass-through interfaces.
307 */
308struct xfer_buffer * xfer_buffer ( struct interface *intf ) {
309 struct interface *dest;
310 xfer_buffer_TYPE ( void * ) *op =
312 void *object = intf_object ( dest );
313 struct interface *xfer_deliver_dest;
314 struct xfer_buffer *xferbuf;
315
316 /* Check that this operation is provided by the same interface
317 * which handles xfer_deliver().
318 */
319 ( void ) intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest );
320
321 if ( op && ( dest == xfer_deliver_dest ) ) {
322 xferbuf = op ( object );
323 } else {
324 /* Default is to not have a data transfer buffer */
325 xferbuf = NULL;
326 }
327
328 intf_put ( xfer_deliver_dest );
329 intf_put ( dest );
330 return xferbuf;
331}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:573
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#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:926
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 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:33
int(* realloc)(struct xfer_buffer *xferbuf, size_t len)
Reallocate data buffer.
Definition xferbuf.h:40
A data transfer buffer.
Definition xferbuf.h:19
size_t len
Size of data.
Definition xferbuf.h:23
size_t max
Maximum required size of data.
Definition xferbuf.h:25
size_t pos
Current offset within data.
Definition xferbuf.h:27
struct xfer_buffer_operations * op
Data transfer buffer operations.
Definition xferbuf.h:29
void * data
Data.
Definition xferbuf.h:21
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:223
struct xfer_buffer * xfer_buffer(struct interface *intf)
Get underlying data transfer buffer.
Definition xferbuf.c:308
static int xferbuf_void_realloc(struct xfer_buffer *xferbuf, size_t len __unused)
Reallocate void data transfer buffer.
Definition xferbuf.c:281
int xferbuf_read(struct xfer_buffer *xferbuf, size_t offset, void *data, size_t len)
Read from data transfer buffer.
Definition xferbuf.c:149
static int xferbuf_umalloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate umalloc()-based data transfer buffer.
Definition xferbuf.c:234
static int xferbuf_malloc_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate malloc()-based data transfer buffer.
Definition xferbuf.c:212
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:88
int xferbuf_write(struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
Write to data transfer buffer.
Definition xferbuf.c:118
struct xfer_buffer_operations xferbuf_void_operations
Void data buffer operations.
Definition xferbuf.c:290
void xferbuf_free(struct xfer_buffer *xferbuf)
Free data transfer buffer.
Definition xferbuf.c:75
void xferbuf_detach(struct xfer_buffer *xferbuf)
Detach data from data transfer buffer.
Definition xferbuf.c:62
struct xfer_buffer_operations xferbuf_fixed_operations
Fixed-size data buffer operations.
Definition xferbuf.c:270
struct xfer_buffer_operations xferbuf_umalloc_operations
umalloc()-based data buffer operations
Definition xferbuf.c:245
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:177
static int xferbuf_fixed_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate fixed-size data transfer buffer.
Definition xferbuf.c:256
Data transfer buffer.
#define xfer_buffer_TYPE(object_type)
Definition xferbuf.h:113