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