blob: fc0b2ed8091ac644269926ad53c9181318804c3a [file] [log] [blame]
Aaron Durbin88b26b82017-03-24 17:10:51 -05001/*
2 * This file is part of the coreboot project.
3 *
Aaron Durbin88b26b82017-03-24 17:10:51 -05004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <commonlib/endian.h>
15#include <commonlib/iobuf.h>
16#include <string.h>
17
18static int ibuf_check_size(const struct ibuf *ib, size_t sz)
19{
20 if (ibuf_remaining(ib) < sz)
21 return -1;
22
23 return 0;
24}
25
26void ibuf_init(struct ibuf *ib, const void *b, size_t sz)
27{
28 ib->b = b;
29 ib->n_read = 0;
30 ib->capacity = sz;
31}
32
33void ibuf_from_obuf(struct ibuf *ib, const struct obuf *ob)
34{
35 ibuf_init(ib, ob->b, ob->n_written);
36}
37
38int ibuf_splice(const struct ibuf *src, struct ibuf *dst, size_t off, size_t sz)
39{
40 size_t end = off + sz;
41 size_t capacity = ibuf_capacity(src);
42 size_t nr_read = ibuf_nr_read(src);
43
44 if (end < off || end < sz || end > capacity)
45 return -1;
46
47 ibuf_init(dst, &src->b[off], sz);
48
49 /* Handle previously read data in src. */
50 if (off < nr_read)
51 dst->n_read = nr_read - off;
52
53 return 0;
54}
55
56int ibuf_splice_current(const struct ibuf *src, struct ibuf *dst, size_t sz)
57{
58 return ibuf_splice(src, dst, ibuf_nr_read(src), sz);
59}
60
61int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b,
62 size_t boundary)
63{
64 if (ibuf_splice(src, a, 0, boundary))
65 return -1;
66
67 return ibuf_splice(src, b, boundary, ibuf_capacity(src) - boundary);
68}
69
70const void *ibuf_oob_drain(struct ibuf *ib, size_t sz)
71{
72 const void *b;
73
74 if (ibuf_check_size(ib, sz))
75 return NULL;
76
77 b = &ib->b[ib->n_read];
78 ib->n_read += sz;
79
80 return b;
81}
82
83int ibuf_read(struct ibuf *ib, void *data, size_t sz)
84{
85 const void *b = ibuf_oob_drain(ib, sz);
86
87 if (b == NULL)
88 return -1;
89
90 memcpy(data, b, sz);
91
92 return 0;
93}
94
95int ibuf_read_be8(struct ibuf *ib, uint8_t *v)
96{
97 size_t sz = sizeof(*v);
98
99 if (ibuf_check_size(ib, sz))
100 return -1;
101
102 *v = read_at_be8(ib->b, ib->n_read);
103 ib->n_read += sz;
104
105 return 0;
106}
107
108int ibuf_read_be16(struct ibuf *ib, uint16_t *v)
109{
110 size_t sz = sizeof(*v);
111
112 if (ibuf_check_size(ib, sz))
113 return -1;
114
115 *v = read_at_be16(ib->b, ib->n_read);
116 ib->n_read += sz;
117
118 return 0;
119}
120
121int ibuf_read_be32(struct ibuf *ib, uint32_t *v)
122{
123 size_t sz = sizeof(*v);
124
125 if (ibuf_check_size(ib, sz))
126 return -1;
127
128 *v = read_at_be32(ib->b, ib->n_read);
129 ib->n_read += sz;
130
131 return 0;
132}
133
134int ibuf_read_be64(struct ibuf *ib, uint64_t *v)
135{
136 size_t sz = sizeof(*v);
137
138 if (ibuf_check_size(ib, sz))
139 return -1;
140
141 *v = read_at_be64(ib->b, ib->n_read);
142 ib->n_read += sz;
143
144 return 0;
145}
146
147int ibuf_read_le8(struct ibuf *ib, uint8_t *v)
148{
149 size_t sz = sizeof(*v);
150
151 if (ibuf_check_size(ib, sz))
152 return -1;
153
154 *v = read_at_le8(ib->b, ib->n_read);
155 ib->n_read += sz;
156
157 return 0;
158}
159
160int ibuf_read_le16(struct ibuf *ib, uint16_t *v)
161{
162 size_t sz = sizeof(*v);
163
164 if (ibuf_check_size(ib, sz))
165 return -1;
166
167 *v = read_at_le16(ib->b, ib->n_read);
168 ib->n_read += sz;
169
170 return 0;
171}
172
173int ibuf_read_le32(struct ibuf *ib, uint32_t *v)
174{
175 size_t sz = sizeof(*v);
176
177 if (ibuf_check_size(ib, sz))
178 return -1;
179
180 *v = read_at_le32(ib->b, ib->n_read);
181 ib->n_read += sz;
182
183 return 0;
184}
185
186int ibuf_read_le64(struct ibuf *ib, uint64_t *v)
187{
188 size_t sz = sizeof(*v);
189
190 if (ibuf_check_size(ib, sz))
191 return -1;
192
193 *v = read_at_le64(ib->b, ib->n_read);
194 ib->n_read += sz;
195
196 return 0;
197}
198
199int ibuf_read_n8(struct ibuf *ib, uint8_t *v)
200{
201 return ibuf_read(ib, v, sizeof(*v));
202}
203
204int ibuf_read_n16(struct ibuf *ib, uint16_t *v)
205{
206 return ibuf_read(ib, v, sizeof(*v));
207}
208
209int ibuf_read_n32(struct ibuf *ib, uint32_t *v)
210{
211 return ibuf_read(ib, v, sizeof(*v));
212}
213
214int ibuf_read_n64(struct ibuf *ib, uint64_t *v)
215{
216 return ibuf_read(ib, v, sizeof(*v));
217}
218
219static int obuf_check_size(const struct obuf *ob, size_t sz)
220{
221 if (obuf_remaining(ob) < sz)
222 return -1;
223
224 return 0;
225}
226
227void obuf_init(struct obuf *ob, void *b, size_t sz)
228{
229 ob->b = b;
230 ob->n_written = 0;
231 ob->capacity = sz;
232}
233
234int obuf_splice(const struct obuf *src, struct obuf *dst, size_t off, size_t sz)
235{
236 size_t end = off + sz;
237 size_t capacity = obuf_capacity(src);
238 size_t nr_written = obuf_nr_written(src);
239
240 if (end < off || end < sz || end > capacity)
241 return -1;
242
243 obuf_init(dst, &src->b[off], sz);
244
245 /* Handle previously written data in src. */
246 if (off < nr_written)
247 dst->n_written = nr_written - off;
248
249 return 0;
250}
251
252int obuf_splice_current(const struct obuf *src, struct obuf *dst, size_t sz)
253{
254 return obuf_splice(src, dst, obuf_nr_written(src), sz);
255}
256
257int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b,
258 size_t boundary)
259{
260 if (obuf_splice(src, a, 0, boundary))
261 return -1;
262
263 return obuf_splice(src, b, boundary, obuf_capacity(src) - boundary);
264}
265
266void *obuf_oob_fill(struct obuf *ob, size_t sz)
267{
268 void *b;
269
270 if (obuf_check_size(ob, sz))
271 return NULL;
272
273 b = &ob->b[ob->n_written];
274 ob->n_written += sz;
275
276 return b;
277}
278
279int obuf_write(struct obuf *ob, const void *data, size_t sz)
280{
281 void *b;
282
283 b = obuf_oob_fill(ob, sz);
284 if (b == NULL)
285 return -1;
286
287 memcpy(b, data, sz);
288
289 return 0;
290}
291
292int obuf_write_be8(struct obuf *ob, uint8_t v)
293{
294 size_t sz = sizeof(v);
295
296 if (obuf_check_size(ob, sz))
297 return -1;
298
299 write_at_be8(ob->b, v, ob->n_written);
300 ob->n_written += sz;
301
302 return 0;
303}
304
305int obuf_write_be16(struct obuf *ob, uint16_t v)
306{
307 size_t sz = sizeof(v);
308
309 if (obuf_check_size(ob, sz))
310 return -1;
311
312 write_at_be16(ob->b, v, ob->n_written);
313 ob->n_written += sz;
314
315 return 0;
316}
317
318int obuf_write_be32(struct obuf *ob, uint32_t v)
319{
320 size_t sz = sizeof(v);
321
322 if (obuf_check_size(ob, sz))
323 return -1;
324
325 write_at_be32(ob->b, v, ob->n_written);
326 ob->n_written += sz;
327
328 return 0;
329}
330
331int obuf_write_be64(struct obuf *ob, uint64_t v)
332{
333 size_t sz = sizeof(v);
334
335 if (obuf_check_size(ob, sz))
336 return -1;
337
338 write_at_be64(ob->b, v, ob->n_written);
339 ob->n_written += sz;
340
341 return 0;
342}
343
344int obuf_write_le8(struct obuf *ob, uint8_t v)
345{
346 size_t sz = sizeof(v);
347
348 if (obuf_check_size(ob, sz))
349 return -1;
350
351 write_at_le8(ob->b, v, ob->n_written);
352 ob->n_written += sz;
353
354 return 0;
355}
356
357int obuf_write_le16(struct obuf *ob, uint16_t v)
358{
359 size_t sz = sizeof(v);
360
361 if (obuf_check_size(ob, sz))
362 return -1;
363
364 write_at_le16(ob->b, v, ob->n_written);
365 ob->n_written += sz;
366
367 return 0;
368}
369
370int obuf_write_le32(struct obuf *ob, uint32_t v)
371{
372 size_t sz = sizeof(v);
373
374 if (obuf_check_size(ob, sz))
375 return -1;
376
377 write_at_le32(ob->b, v, ob->n_written);
378 ob->n_written += sz;
379
380 return 0;
381}
382
383int obuf_write_le64(struct obuf *ob, uint64_t v)
384{
385 size_t sz = sizeof(v);
386
387 if (obuf_check_size(ob, sz))
388 return -1;
389
390 write_at_le64(ob->b, v, ob->n_written);
391 ob->n_written += sz;
392
393 return 0;
394}
395
396int obuf_write_n8(struct obuf *ob, uint8_t v)
397{
398 return obuf_write(ob, &v, sizeof(v));
399}
400
401int obuf_write_n16(struct obuf *ob, uint16_t v)
402{
403 return obuf_write(ob, &v, sizeof(v));
404}
405
406int obuf_write_n32(struct obuf *ob, uint32_t v)
407{
408 return obuf_write(ob, &v, sizeof(v));
409}
410
411int obuf_write_n64(struct obuf *ob, uint64_t v)
412{
413 return obuf_write(ob, &v, sizeof(v));
414}
415
416const void *obuf_contents(const struct obuf *ob, size_t *sz)
417{
418 *sz = obuf_nr_written(ob);
419 return ob->b;
420}