Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / core / xferbuf.c
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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ipxe/xfer.h>
26 #include <ipxe/iobuf.h>
27 #include <ipxe/xferbuf.h>
28
29 /** @file
30  *
31  * Data transfer buffer
32  *
33  */
34
35 /**
36  * Finish using data transfer buffer
37  *
38  * @v xferbuf           Data transfer buffer
39  */
40 void xferbuf_done ( struct xfer_buffer *xferbuf ) {
41         free ( xferbuf->data );
42         xferbuf->data = NULL;
43         xferbuf->len = 0;
44         xferbuf->pos = 0;
45 }
46
47 /**
48  * Ensure that data transfer buffer is large enough for the specified size
49  *
50  * @v xferbuf           Data transfer buffer
51  * @v len               Required minimum size
52  * @ret rc              Return status code
53  */
54 static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
55         void *new_data;
56
57         /* If buffer is already large enough, do nothing */
58         if ( len <= xferbuf->len )
59                 return 0;
60
61         /* Extend buffer */
62         new_data = realloc ( xferbuf->data, len );
63         if ( ! new_data ) {
64                 DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
65                        "%zd bytes\n", xferbuf, len );
66                 return -ENOSPC;
67         }
68         xferbuf->data = new_data;
69         xferbuf->len = len;
70
71         return 0;
72 }
73
74 /**
75  * Add received data to data transfer buffer
76  *
77  * @v xferbuf           Data transfer buffer
78  * @v iobuf             I/O buffer
79  * @v meta              Data transfer metadata
80  * @ret rc              Return status code
81  */
82 int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
83                       struct xfer_metadata *meta ) {
84         size_t len;
85         size_t max;
86         int rc;
87
88         /* Calculate new buffer position */
89         if ( meta->flags & XFER_FL_ABS_OFFSET )
90                 xferbuf->pos = 0;
91         xferbuf->pos += meta->offset;
92
93         /* Ensure that we have enough buffer space for this data */
94         len = iob_len ( iobuf );
95         max = ( xferbuf->pos + len );
96         if ( ( rc = xferbuf_ensure_size ( xferbuf, max ) ) != 0 )
97                 goto done;
98
99         /* Copy data to buffer */
100         memcpy ( ( xferbuf->data + xferbuf->pos ), iobuf->data, len );
101
102         /* Update current buffer position */
103         xferbuf->pos += len;
104
105  done:
106         free_iob ( iobuf );
107         return rc;
108 }